home *** CD-ROM | disk | FTP | other *** search
/ Electronic Clipper 1995 April / Electronic Clipper 1995-04.iso / pc / pc_users / ideasrc / setup / pviewer / pictwnd.c < prev    next >
Text File  |  1993-04-17  |  101KB  |  2,392 lines

  1.  
  2. // ---------------------------------------------------------------------
  3. //
  4. // PictWnd.c - Picture Viewer - QuickTime for Windows
  5. //
  6. //             Version 1.0
  7. //
  8. //             (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
  9. //
  10. // ---------------------------------------------------------------------
  11.  
  12.  
  13. // Includes
  14. // --------
  15.    #include <Windows.H>              // Required by Windows
  16.    #include <commdlg.h>              // Required for PRINTDLG struct
  17.    #include <stdio.h>                // Required for sprintf routine
  18.    #include <stdlib.h>               // Required for fullpath routine
  19.    #include <sys\types.h>            // Required for stat.h
  20.    #include <sys\stat.h>             // Required for _stat routine
  21.  
  22.    #include <qtw.h>                  // Interface to QuickTime
  23.    #include <qtole.h>                // Interface to qtole dll
  24.    #include "common.h"               // Interface to common.c
  25.  
  26.    #include "viewer.h"               // Interface to other *.c files
  27.    #include "viewer.hr"              // Defines used in *.rc files
  28.    #include "picture.h"              // Interface to child window processing
  29.  
  30. // Constants
  31. // ---------
  32.    #define GETINFOPICTUREPROP    "Picture"   // Used in initializing info dialog
  33.    #define SIZE_COLOR_TABLE     ( 256 * sizeof( RGBQUAD ))
  34.  
  35. // Message-Persistent Data
  36. // -----------------------
  37.    static struct                     // Hungarian notation: g
  38.      { WORD      wPictureCount;      // Used during enumeration for
  39.                                      // duplication checking
  40.        BOOL      bCreating;          //   "    "       "
  41.        HWND      hwndFirstDup;       //   "    "       "
  42.        HICON     hpictIcon;          // Picture wnd icon
  43.        HPALETTE  hpalCurrentSystem;  // Current system palette
  44.        RECT      rcSelection;        // Selection rect
  45.  
  46.      } g;
  47.  
  48. // Macros
  49. // ----------------------------
  50.    #define ISKEYDOWN( vKey )    ( GetKeyState( (int) (vKey) ) < 0 )
  51.          // Next macro is from windowsx.h
  52.    #define GlobalPtrHandle(lp)   \
  53.                   ( (HGLOBAL) LOWORD( GlobalHandle( SELECTOROF( lp ))))
  54.  
  55.  
  56. // Exported callback function
  57. // ----------------------------
  58.    BOOL __export CALLBACK GetInfoDlgProc     (HWND, UINT, WPARAM, LPARAM);
  59.    BOOL __export CALLBACK CheckDupEnumProc   (HWND, LPARAM);
  60.  
  61.  
  62. // Internal Function Declarations
  63. // ------------------------------
  64.    static LONG    NEAR ViewerPictureCreate      (HWND, LPARAM );
  65.    static LONG    NEAR ViewerEditCommands       (HWND, WPARAM, WORD);
  66.    static LONG    NEAR ViewerImageCommands      (HWND, WPARAM, WORD);
  67.    static LONG    NEAR PrintPicture             (HWND, LPPRINTDLG);
  68.    static VOID    NEAR FillPictureInfo          (HWND, NPPICTUREDATA);
  69.    static VOID    NEAR UpdateInfoFileName       (HWND, NPPICTUREDATA);
  70.    static VOID    NEAR UpdateInfoCurrentSize    (HWND, NPPICTUREDATA);
  71.    static LONG    NEAR InitializePopupMenus     (HWND, HMENU, int);
  72.    static LONG    NEAR PaintThePicture          (HWND);
  73.    static LONG    NEAR PaintTheIcon             (HWND);
  74.    static LONG    NEAR KeyDownMessage           (HWND, WPARAM, LPARAM);
  75.    static BOOL    NEAR BuildIconBitmap          (HWND, NPPICTUREDATA);
  76.  
  77.    static BOOL    NEAR InitSelection            (HWND, POINT);
  78.    static VOID    NEAR MoveTheSelectRect        (HWND, POINT);
  79.    static VOID    NEAR EndTheSelection          (HWND);
  80.    static VOID    NEAR DrawSelectionRect        (HWND, HDC, NPPICTUREDATA);
  81.  
  82.    static VOID    NEAR SetOptionsDefaults       (HWND, NPPICTUREDATA);
  83.    static VOID    NEAR PopulateOptionsStruct    (HWND, NPPICTUREDATA);
  84.  
  85.  
  86. // Function: ViewerPictureWndProc - Viewer picture Window Procedure
  87. // --------------------------------------------------------------------
  88. // Parameters: As required by Microsoft Windows
  89. //
  90. // Returns:    Via DefMDIChildProc
  91. // --------------------------------------------------------------------
  92.    LONG __export CALLBACK ViewerPictureWndProc
  93.              (HWND hwndPicture, UINT message, WPARAM wParam, LPARAM lParam)
  94.  
  95.      {NPPICTUREDATA    pPictureData;       // Temp -> to picture data struct
  96.       HPICTUREDATA     hPictureData;       // Temp handle to picture data
  97.       WNDENUMPROC      lpfnEnumPictures;   // -> enumeration proc
  98.       NPPICTUREDATA    pFirstPictureData;  // Temp -> to picture data
  99.                                            // struct. Used during duplication
  100.                                            // processing
  101.       HDC              hdc;                // Window hdc
  102.       HPALETTE         hpalSave;           // Prev palette
  103.       POINT            ptCursor;           // Cursor position used in grow box
  104.       LPNCCALCSIZE_PARAMS lpncsp;          // -> NCCCALCSIZE_PARAMS struct
  105.       LPQTOLE_OLEDATA  lpOleData;          // -> ole data
  106.  
  107.       static BOOL      bDragging;          // Flag set when using grow box
  108.       static BOOL      bSelecting;         // Flag set when making a selection
  109.  
  110.       switch( message )
  111.         {case WM_CREATE:
  112.                 // Load picture frame icon used by all instances
  113.             if( !g.hpictIcon )
  114.                 g.hpictIcon = LoadIcon( ViewerQueryResources(),
  115.                                        MAKEINTRESOURCE( VIEWER_PICT_ICON ));
  116.             return ViewerPictureCreate( hwndPicture , lParam );
  117.  
  118.          case WM_SIZE:
  119.                 // Turn off the max size limits set during
  120.                 // WM_NCLBUTTONDOWN processing
  121.             if( bDragging )
  122.                {LimitTheDragSize( hwndPicture, bDragging = FALSE );
  123.                }
  124.  
  125.                 // This routine also updates scrolling parameters
  126.             ResizeKids( hwndPicture, LOWORD( lParam ), HIWORD( lParam ));
  127.  
  128.             break;   // Break to DefMDIChildProc
  129.  
  130.  
  131.             // We don't use the CS_HREDRAW | CS_VREDRAW so we need to
  132.             // tell when to repaint the entire picture. We repaint the whole
  133.             // thing if the UL corner moves or either of the scroll
  134.             // bars is enabled.
  135.          case WM_NCCALCSIZE:
  136.             if( wParam )
  137.                {lpncsp = (LPNCCALCSIZE_PARAMS) lParam;
  138.                 if( !( pPictureData =
  139.                        (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) ||
  140.                        ( lpncsp->rgrc[0].left != lpncsp->rgrc[1].left ) ||
  141.                        ( lpncsp->rgrc[0].top  != lpncsp->rgrc[1].top ) ||
  142.                       IsWindowEnabled( pPictureData->spmsHScroll.hwnd ) ||
  143.                       IsWindowEnabled( pPictureData->spmsVScroll.hwnd ))
  144.                    {InvalidateRect( hwndPicture, NULL, FALSE );
  145.                    }
  146.                 else if( ( lpncsp->rgrc[0].right  > lpncsp->rgrc[1].right ) ||
  147.                            ( lpncsp->rgrc[0].bottom > lpncsp->rgrc[1].bottom ))
  148.                    { // Paint out the grow box. At this point, the grow box rect
  149.                      // still contains the old rect since this message occurs
  150.                      // before the WM_SIZE message
  151.                     InvalidateRect( hwndPicture,
  152.                                            &pPictureData->rcGrowBox, FALSE );
  153.                    }
  154.                }
  155.  
  156.             break;   // Break to DefMDIChildProc
  157.  
  158.             // This tells windows to treat the grow box like the
  159.             // bottom right window frame
  160.          case WM_NCHITTEST:
  161.             if( !IsZoomed( hwndPicture ))
  162.                {ptCursor = MAKEPOINT( lParam );
  163.                 ScreenToClient( hwndPicture, &ptCursor );
  164.                 if( IsInGrowBox( hwndPicture, ptCursor ))
  165.                     return HTBOTTOMRIGHT;
  166.                }
  167.  
  168.             break;   // Break to DefMDIChildProc
  169.  
  170.  
  171.             // Set the cursor to the arrow cursor in the grow box
  172.             // Because of the WM_NCHITTEST processing we do, Windows
  173.             // thinks it is in the corner border and will set the
  174.             // cursor to the diagonal arrow.
  175.          case WM_SETCURSOR:
  176.             if( LOWORD( lParam ) == HTBOTTOMRIGHT )
  177.                {GetCursorPos( &ptCursor );
  178.                 ScreenToClient( hwndPicture, &ptCursor );
  179.                 if( IsInGrowBox( hwndPicture, ptCursor ))
  180.                    {SetCursor( LoadCursor( NULL, IDC_ARROW ));
  181.                     return 1L;
  182.                    }
  183.                }
  184.             break;  // Break to DefMDIChildProc
  185.  
  186.             // Limit the window size so that the grow box resized window
  187.             // stays inside the MDI client rect
  188.          case WM_NCLBUTTONDOWN:
  189.             if( wParam == HTBOTTOMRIGHT )
  190.                {ptCursor = MAKEPOINT( lParam );
  191.                 ScreenToClient( hwndPicture, &ptCursor );
  192.                 if( IsInGrowBox( hwndPicture, ptCursor ))
  193.                    {LimitTheDragSize( hwndPicture, bDragging = TRUE );
  194.                    }
  195.                }
  196.  
  197.             break;  // Break to DefMDIChildProc
  198.  
  199.  
  200.     // WM_LBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP are used to implement
  201.     // grow box resizing of the frame window when the window is maximized
  202.          case WM_LBUTTONDOWN:
  203.             if( IsZoomed( hwndPicture ) &&
  204.                    !IsZoomed( ViewerQueryFrameWindow()) &&
  205.                      IsInGrowBox( hwndPicture, MAKEPOINT( lParam )) &&
  206.                 ( bDragging = InitMaxWndGrowBoxResize
  207.                                    ( hwndPicture, MAKEPOINT( lParam ))))
  208.                {SetCapture( hwndPicture );
  209.                }
  210.             else if( bSelecting = InitSelection
  211.                                     ( hwndPicture, MAKEPOINT( lParam )))
  212.                {SetCapture( hwndPicture );
  213.                }
  214.  
  215.             return 0L;
  216.  
  217.          case WM_MOUSEMOVE:
  218.             if( bDragging && IsZoomed( hwndPicture ))
  219.                {MoveTheFrameRect( hwndPicture, MAKEPOINT( lParam ));
  220.                }
  221.             else if( bSelecting )
  222.                {MoveTheSelectRect( hwndPicture, MAKEPOINT( lParam ));
  223.                }
  224.  
  225.             return 0L;
  226.  
  227.          case WM_LBUTTONUP:
  228.             if( bDragging && IsZoomed( hwndPicture ))
  229.                {EndMaxWndGrowBoxResize( hwndPicture );
  230.                 bDragging = FALSE;
  231.                 ReleaseCapture();
  232.                }
  233.             else if( bSelecting )
  234.                {EndTheSelection( hwndPicture );
  235.                 bSelecting = FALSE;
  236.                 ReleaseCapture();
  237.                }
  238.  
  239.             return 0L;
  240.  
  241.  
  242.          case WM_NCACTIVATE:
  243.             if( !( pPictureData =
  244.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  245.                 break;  // Break to DefMDIChildProc
  246.  
  247.             if( (BOOL) wParam )
  248.                {  // Set flag to disable the scroll bar processing. Although this
  249.                   // is only necessary in the case of palettized devices, it is
  250.                   // done in all cases in order to have a consistent user interface.
  251.                   // This disabling is necessary in order to avoid a problem with
  252.                   // simultaneous scrolling and palette switching that leaves a
  253.                   // portion of the picture incorrectly updated.
  254.                   // The visual effect of this disabling is that clicking on a
  255.                   // scroll bar will activate the window but will not cause the
  256.                   // scolling to actually occur.
  257.  
  258.                 pPictureData->bScrollWaitForPaint = TRUE;
  259.  
  260.                   // Realize palette if activating and is palettized device
  261.                 if( ViewerIsPalettized())
  262.                    {if( pPictureData->hpalPicture &&
  263.                                              ( hdc = GetDC( hwndPicture )))
  264.                        {hpalSave = SelectPalette
  265.                                     ( hdc, pPictureData->hpalPicture, 0 );
  266.  
  267.                         StoreCurrentSystemPalette
  268.                                               ( pPictureData->hpalPicture );
  269.                         RealizePalette( hdc );
  270.  
  271.                         SelectPalette( hdc, hpalSave, 0 );
  272.                         ReleaseDC( hwndPicture, hdc );
  273.  
  274.                         InvalidateRect( hwndPicture, NULL, FALSE );
  275.                        }
  276.                     else if( GetUpdateRect( hwndPicture, NULL, FALSE ))
  277.                         InvalidateRect( hwndPicture, NULL, FALSE );
  278.                    }
  279.                 else
  280.                    { // Post message to reable scrolling because generally will
  281.                      // not get a WM_PAINT message. Don't want to use
  282.                      // InvalidateRect() because it will generate an unnessary
  283.                      // repaint.
  284.                     PostMessage( hwndPicture, WM_VIEWER_REENABLESCROLL, 0, 0L );
  285.                    }
  286.                }
  287.  
  288.             break;  // Break to DefMDIChildProc
  289.  
  290.          case WM_SYSCOMMAND:
  291.                    // Each picture needs an icon bitmap. We build it here
  292.                    // because the window must have first realized the palette.
  293.                    // This message appears after the WM_NCACTIVATE
  294.                    // message for this window and before the WM_NCACTIVATE
  295.                    // for the window that will eventually be activated.
  296.                    // This bitmap will be created and saved the first time
  297.                    // the window is iconized
  298.             if( ( wParam == SC_MINIMIZE ) &&
  299.                   ( pPictureData =
  300.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) &&
  301.                   !pPictureData->hbitmapIcon && !pPictureData->lpDIBIconMem )
  302.                {BuildIconBitmap( hwndPicture, pPictureData );
  303.                }
  304.  
  305.             break;  // Break to DefMDIChildProc
  306.  
  307.          case WM_COMMAND:
  308.             switch( wParam )
  309.                {case VIEWER_EDIT_COPYPICTURE:   // edit menu popup
  310.                 case VIEWER_EDIT_OPTIONS:
  311.                 case VIEWER_EDIT_CANCELSEL:
  312.                     return ViewerEditCommands
  313.                                   ( hwndPicture, wParam, HIWORD (lParam));
  314.  
  315.                 case VIEWER_IMAGE_GETINFO:    // image menu popup
  316.                 case VIEWER_IMAGE_HALFSIZE:
  317.                 case VIEWER_IMAGE_NORMALSIZE:
  318.                 case VIEWER_IMAGE_DOUBLESIZE:
  319.                     return ViewerImageCommands
  320.                                   ( hwndPicture, wParam, HIWORD( lParam ));
  321.  
  322.                 default:
  323.                     break;  // Break to DefMDIChildProc
  324.                }
  325.  
  326.              break;
  327.  
  328.          case WM_KEYDOWN:
  329.             return KeyDownMessage( hwndPicture, wParam, lParam );
  330.  
  331.     // WM_USER messages
  332.  
  333.          case WM_VIEWER_PRINTPICTURE:
  334.             return PrintPicture( hwndPicture, (LPPRINTDLG) lParam );
  335.  
  336.          case WM_VIEWER_INITPOPUPS:
  337.             return InitializePopupMenus
  338.                     ( hwndPicture, (HMENU) wParam, (int) LOWORD( lParam ));
  339.  
  340.          case WM_VIEWER_REENABLESCROLL:
  341.             if( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))
  342.                 pPictureData->bScrollWaitForPaint = FALSE;
  343.             return 0L;
  344.  
  345.     // end WM_USER messages
  346.  
  347.  
  348.          case WM_ERASEBKGND:
  349.               // If there is a picture, let it deal with the background in
  350.               // WM_PAINT
  351.             return ((pPictureData =
  352.                   (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) != NULL );
  353.  
  354.          case WM_HSCROLL:
  355.             if( !( pPictureData = (NPPICTUREDATA)
  356.                         GetWindowWord( hwndPicture, 0 )) ||
  357.                               pPictureData->bScrollWaitForPaint )
  358.                {return 0L;
  359.                }
  360.             else
  361.                {return ProcessHorzScroll
  362.                       ( hwndPicture, (WORD) wParam, LOWORD( lParam ));
  363.                }
  364.  
  365.          case WM_VSCROLL:
  366.             if( !( pPictureData = (NPPICTUREDATA)
  367.                         GetWindowWord( hwndPicture, 0 )) ||
  368.                               pPictureData->bScrollWaitForPaint )
  369.                {return 0L;
  370.                }
  371.             else
  372.                {return ProcessVertScroll
  373.                       ( hwndPicture, (WORD) wParam, LOWORD( lParam ));
  374.                }
  375.  
  376.          case WM_GETMINMAXINFO:
  377.             SetMinMaxInfo( (MINMAXINFO FAR*) lParam );
  378.             break; // Break to DefMDIChildProc
  379.  
  380.          case WM_QUERYDRAGICON:
  381.             return MAKELONG( g.hpictIcon, 0 );
  382.  
  383.          case WM_PAINT:
  384.             if( IsIconic( hwndPicture ))
  385.                 return PaintTheIcon( hwndPicture );
  386.             else
  387.                {if( PaintThePicture( hwndPicture ))
  388.                    {  // Draw picture failed so close window
  389.                     PostMessage( hwndPicture, WM_CLOSE, 0, 0L );
  390.                    }
  391.                 else if( pPictureData = (NPPICTUREDATA)
  392.                               GetWindowWord( hwndPicture, 0 ))
  393.                     pPictureData->bScrollWaitForPaint = FALSE;
  394.  
  395.                 return 0L;
  396.                }
  397.  
  398.          case WM_DESTROY:
  399.              if( ( pPictureData = (NPPICTUREDATA)
  400.                                   GetWindowWord( hwndPicture, 0 )) &&
  401.                  ( lpOleData = ViewerQueryOleData()) && lpOleData->lpqtoleServer )
  402.                 {PopulateOptionsStruct( hwndPicture, pPictureData );
  403.                  if( !QTOLE_ClosingDocWnd( lpOleData,
  404.                                (LPQTOLE_OPTIONS) &pPictureData->qtoleOptions ))
  405.                      return 0L;
  406.                 }
  407.  
  408.              break;  // break to DefMDIChildProc
  409.  
  410.                // Process WM_NCDESTROY instead of WM_DESTROY so that child controls
  411.                // get WM_DESTROY messages before the stuff in here get executed
  412.          case WM_NCDESTROY:
  413.             if( !(pPictureData =
  414.                           (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  415.                 break;
  416.  
  417.             if( pPictureData->hwndGetInfo )
  418.                 DestroyWindow( pPictureData->hwndGetInfo );
  419.  
  420.             if( pPictureData->phPicture != NULL)
  421.                 DisposePicture( pPictureData->phPicture );
  422.  
  423.             if( pPictureData->hpalPicture )
  424.                 DeleteObject( pPictureData->hpalPicture );
  425.  
  426.             if( pPictureData->hbitmapIcon )
  427.                 DeleteObject( pPictureData->hbitmapIcon );
  428.             if( pPictureData->lpDIBIconMem )
  429.                {GlobalUnlock( GlobalPtrHandle( pPictureData->lpDIBIconMem ));
  430.                 GlobalFree( GlobalPtrHandle( pPictureData->lpDIBIconMem ));
  431.                }
  432.  
  433.                 // Last instance destroys icon stuff
  434.             if( ViewerQueryNumPictures() <= 1 )
  435.                {if( g.hpictIcon )
  436.                    {DestroyIcon( g.hpictIcon );
  437.                     g.hpictIcon = NULL;
  438.                    }
  439.                 g.hpalCurrentSystem = NULL;
  440.                 DestroyGrowBoxBitmap();
  441.                }
  442.             else  // Check for duplicates
  443.                {g.wPictureCount = 0;
  444.                 g.bCreating     = FALSE;
  445.                 g.hwndFirstDup  = NULL;
  446.                 if( lpfnEnumPictures = (WNDENUMPROC) MakeProcInstance
  447.                      ( (FARPROC) CheckDupEnumProc, ViewerQueryInstance()))
  448.                    {EnumChildWindows( ViewerQueryClientWindow(),
  449.                           lpfnEnumPictures, MAKELPARAM( hwndPicture, 0 ));
  450.                     FreeProcInstance( (FARPROC) lpfnEnumPictures );
  451.  
  452.                    // if no dups, eliminate :1 on first
  453.                    // hwndFirstDup is set in CheckDupEnumProc
  454.                     if( ( g.wPictureCount == 1 ) && g.hwndFirstDup &&
  455.                          ( pFirstPictureData = (NPPICTUREDATA)
  456.                                      GetWindowWord( g.hwndFirstDup, 0 )))
  457.                        {pFirstPictureData->wDuplicationIndex = 0;
  458.                         SetWindowText( g.hwndFirstDup,
  459.                                         pFirstPictureData->szPictureName );
  460.                        }
  461.                    }
  462.                }
  463.  
  464.             LocalUnlock( hPictureData =
  465.                             (HPICTUREDATA) LocalHandle( pPictureData ));
  466.             LocalFree( hPictureData );
  467.             SetWindowWord( hwndPicture, 0, 0 ); // Set this to 0 for any
  468.                                                 // subsequent messages
  469.  
  470.             SendMessage( ViewerQueryFrameWindow(),
  471.                       WM_VIEWER_PICTUREDELETED, (WPARAM) hwndPicture, 0L );
  472.  
  473.             break;  // break to DefMDIChildProc
  474.  
  475.         }
  476.  
  477.       return DefMDIChildProc( hwndPicture, message, wParam, lParam );
  478.      }
  479.  
  480.  
  481. // Function: ViewerPictureCreate - process WM_CREATE message
  482. // --------------------------------------------------------------------
  483. // Parameters: HWND       hwndPicture      Handle of picture window
  484. //             LPARAM     lParam           lParam of WM_CREATE message
  485. //
  486. // Returns:    0L if OK, else returns -1L to kill app
  487. // --------------------------------------------------------------------
  488.    static LONG NEAR ViewerPictureCreate( HWND hwndPicture, LPARAM lParam )
  489.  
  490.      {NPPICTUREDATA      pPictureData;     // Temp -> to picture data struct
  491.       HPICTUREDATA       hPictureData;     // Handle to picture data struct
  492.       LPMDICREATESTRUCT  lpmdicreate;      // MDI create struct
  493.       struct _stat       statbuf;          // File statictics struct
  494.       char               szBuffer[MAX_PATH_LEN];  // Temp buffer
  495.       DWORD              dwBytes;          // File size
  496.       OSErr              oserr;            // Error return
  497.       WORD               wIDString1;       // Resource string id
  498.       WORD               wIDString2;       // Resource string id
  499.       POINT              ptCorner;         // Upper Left corner of pict wnd
  500.       RECT               rcWindow;         // Window rect
  501.       int                nDiff;            // Temp
  502.       RECT               rcclientClient;   // Client rect of MDI client wnd
  503.       WORD               wWidth;           // Width of window
  504.       WORD               wHeight;          // Height of window
  505.       WNDENUMPROC        lpfnEnumPictures; // -> to enumeration proc
  506.       LPSTR              lpName;           // Temp -> picture name
  507.       PicFile            picPicFile;       // Picture file handle
  508.       HDC                hdc;              // Window hdc
  509.       HCURSOR            hcursorSave;      // Prior cursor
  510.       char               szCompressor[sizeof(DWORD) + 1]; // compressor type
  511.       QTOLE_OPENWND      qtoleOpenWnd;     // Ole open wnd struct
  512.       LPQTOLE_OLEDATA    lpOleData;        // -> ole data
  513.       WORD               wZoomIndex;       // Initial zoom index
  514.  
  515.  
  516.       pPictureData = (NPPICTUREDATA) NULL;
  517.       szBuffer[0] = '\0';
  518.       hcursorSave = NULL;
  519.  
  520.       if( !(hPictureData = (HPICTUREDATA)
  521.                            LocalAlloc( LPTR, sizeof( PICTUREDATASTRUCT ))))
  522.          {CommonTellUser( ViewerQueryResources(),
  523.                                     VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  524.           goto Failed;
  525.          }
  526.       pPictureData = (NPPICTUREDATA) LocalLock( hPictureData );
  527.       SetWindowWord( hwndPicture, 0, (WORD) pPictureData );
  528.  
  529.    // mdi struct filled before call to MDI create in LaunchPictureWnd
  530.       lpmdicreate = (LPMDICREATESTRUCT)
  531.                                ((LPCREATESTRUCT) lParam)->lpCreateParams;
  532.  
  533.       lstrcpy( pPictureData->szPictureName, (LPSTR) lpmdicreate->szTitle );
  534.  
  535.    // Strip off and save extension so that name fits better
  536.    // on title bar of window
  537.       pPictureData->szPictureExt[0] = '\0';
  538.       lpName = pPictureData->szPictureName;
  539.       while( *lpName )
  540.          {if( *lpName == '.' )
  541.             {lstrcpy( pPictureData->szPictureExt, lpName );
  542.              *lpName = '\0';
  543.              SetWindowText( hwndPicture, pPictureData->szPictureName );
  544.              break;
  545.             }
  546.           else
  547.             lpName = AnsiNext( lpName );
  548.          }
  549.  
  550.    // Open picture file and extract picture
  551.       hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  552.    // Cache path
  553.       lstrcpy( pPictureData->szPicturePath, (LPSTR) lpmdicreate->lParam );
  554.       if( OpenPictureFile( pPictureData->szPicturePath,
  555.                                                 &picPicFile, OF_READ ))
  556.          {CommonTellUser( ViewerQueryResources(),
  557.                       VIEWER_STRING_NOOPENFILE, VIEWER_STRING_CAPTION,
  558.                                  MB_OK, (LPSTR) lpmdicreate->szTitle );
  559.           goto Failed;
  560.          }
  561.  
  562.       pPictureData->phPicture = GetPictureFromFile( picPicFile );
  563.       ClosePictureFile( picPicFile );
  564.  
  565.       if( !pPictureData->phPicture )
  566.          {if( ( oserr = GetMoviesStickyError()) == noPictureInFile )
  567.               wIDString1 = VIEWER_STRING_NOPICINFILE;
  568.           else if( oserr == insufficientMemory )
  569.               wIDString1 = VIEWER_STRING_NOMEMORY;
  570.           else
  571.               wIDString1 = VIEWER_STRING_NOGETPIC;
  572.  
  573.           ClearMoviesStickyError();
  574.  
  575.           CommonTellUser( ViewerQueryResources(),
  576.                         wIDString1, VIEWER_STRING_CAPTION,
  577.                                  MB_OK, (LPSTR) lpmdicreate->szTitle );
  578.           goto Failed;
  579.          }
  580.  
  581.    // Check for duplicates. Fix up titles if necessary
  582.           // Initialize globals used during enumeration
  583.       g.wPictureCount = 1;
  584.       g.bCreating =  TRUE;
  585.       if( ( ViewerQueryNumPictures() > 0 ) &&
  586.           ( lpfnEnumPictures = (WNDENUMPROC) MakeProcInstance
  587.                       ( (FARPROC) CheckDupEnumProc, ViewerQueryInstance())))
  588.          {EnumChildWindows( ViewerQueryClientWindow(),
  589.                           lpfnEnumPictures, MAKELPARAM( hwndPicture, 0 ));
  590.           FreeProcInstance( (FARPROC) lpfnEnumPictures );
  591.  
  592.              // Fix up title if duplicate
  593.              // Title of 1st dup is fixed up during enum
  594.           if( g.wPictureCount > 1 )
  595.              {pPictureData->wDuplicationIndex = g.wPictureCount;
  596.               wsprintf( szBuffer, "%s:%u",
  597.                                     (LPSTR) pPictureData->szPictureName,
  598.                                          pPictureData->wDuplicationIndex );
  599.               SetWindowText( hwndPicture, szBuffer );
  600.              }
  601.          }
  602.  
  603.    // Get the palette for the picture if the monitor is palettized
  604.    // A default palette is returned if the picture does not have a palette
  605.       pPictureData->hpalPicture = NULL;
  606.       if( ViewerIsPalettized() && ( hdc = GetDC( hwndPicture )))
  607.          {pPictureData->hpalPicture =
  608.                             GetPicturePalette( pPictureData->phPicture );
  609.           ReleaseDC( hwndPicture, hdc );
  610.          }
  611.  
  612.  
  613.    // Get file size  Note: Need to switch to OEM char set.
  614.    // Sizes are displayed in banner bar and in info dialog
  615.       AnsiToOem( pPictureData->szPicturePath, szBuffer );
  616.       if( (_stat( szBuffer, &statbuf )) == 0 )
  617.          {if( statbuf.st_size < 1000L )
  618.              {dwBytes = (DWORD) statbuf.st_size;
  619.               wIDString1 = VIEWER_STRING_SIZEBYTES;
  620.               wIDString2 = VIEWER_STRING_SIZEBYTESONDISK;
  621.              }
  622.           else
  623.              {dwBytes =  (DWORD) ( statbuf.st_size / 1000L );
  624.               wIDString1 = VIEWER_STRING_SIZEKBYTES;
  625.               wIDString2 = VIEWER_STRING_SIZEKBYTESONDISK;
  626.              }
  627.  
  628.           LoadString( ViewerQueryResources(),
  629.                                  wIDString1, szBuffer, sizeof( szBuffer ));
  630.           wsprintf( pPictureData->szFileSize, szBuffer, dwBytes );
  631.           LoadString( ViewerQueryResources(),
  632.                                  wIDString2, szBuffer, sizeof( szBuffer ));
  633.           wsprintf( pPictureData->szFileSizeOnDisk, szBuffer, dwBytes );
  634.          }
  635.  
  636.  
  637.       pPictureData->idImageInfo.idSize = sizeof( ImageDescription );
  638.       if( GetPictureInfo( pPictureData->phPicture, &pPictureData->idImageInfo ))
  639.          {CommonTellUser( ViewerQueryResources(),
  640.                      VIEWER_STRING_NOINFO, VIEWER_STRING_CAPTION, MB_OK );
  641.           goto Failed;
  642.          }
  643.  
  644.           // Picture type
  645.       if( pPictureData->idImageInfo.name[0] )
  646.          {lstrcpy( pPictureData->szPictType, pPictureData->idImageInfo.name );
  647.          }
  648.       else
  649.          {  // Compressor type is stored as a DWORD. i.e. 'jpeg'
  650.           if( pPictureData->idImageInfo.CodecType )
  651.              {*((PDWORD) &szCompressor) = pPictureData->idImageInfo.CodecType;
  652.               szCompressor[ sizeof(DWORD) ] = '\0';
  653.              }
  654.  
  655.           pPictureData->szPictType[0] = '\0';
  656.             // Spaces in "raw ", "rle " etc are necessary !!!
  657.           if( !pPictureData->idImageInfo.CodecType ||
  658.                                             !lstrcmpi( szCompressor, "raw " ))
  659.               wIDString1 = VIEWER_STRING_CODEC_NONE;
  660.           else if( !lstrcmpi( szCompressor, "jpeg" ))
  661.               wIDString1 = VIEWER_STRING_CODEC_PHOTO;
  662.           else if( !lstrcmpi( szCompressor, "rle " ))
  663.               wIDString1 = VIEWER_STRING_CODEC_ANIMATION;
  664.           else if( !lstrcmpi( szCompressor, "smc " ))
  665.               wIDString1 = VIEWER_STRING_CODEC_GRAPHICS;
  666.           else if( !lstrcmpi( szCompressor, "rpza" ))
  667.               wIDString1 = VIEWER_STRING_CODEC_VIDEO;
  668.           else if( !lstrcmpi( szCompressor, "cvid" ))
  669.               wIDString1 = VIEWER_STRING_CODEC_CVID;
  670.           else
  671.               wIDString1 = VIEWER_STRING_CODEC_NONE;
  672.  
  673.           LoadString( ViewerQueryResources(), wIDString1,
  674.               pPictureData->szPictType, sizeof( pPictureData->szPictType ));
  675.          }
  676.  
  677.          // Adjust resolution for Mac wierdness
  678.       if( ( pPictureData->idImageInfo.hRes == -1 ) &&
  679.                                       ( pPictureData->idImageInfo.vRes == -1 ))
  680.           pPictureData->idImageInfo.hRes =
  681.                           pPictureData->idImageInfo.vRes = MAKELFIXED( 72, 0 );
  682.       else if( pPictureData->idImageInfo.hRes == -1 )
  683.           pPictureData->idImageInfo.hRes = pPictureData->idImageInfo.vRes;
  684.       else if( pPictureData->idImageInfo.vRes == -1 )
  685.           pPictureData->idImageInfo.vRes = pPictureData->idImageInfo.hRes;
  686.  
  687.          // Initialize this to something impossible so that
  688.          // size checking tests in ZoomPicture, etc will work
  689.          // during startup
  690.       pPictureData->zsZoomScroll.wCurZoomIndex = IMAGE_SIZE_FIRST - 1;
  691.  
  692.    // Create the picture window controls
  693.       if( CreateViewerKids( hwndPicture, pPictureData ))
  694.           goto Failed;   // Errors reported by function
  695.  
  696.       pPictureData->spmsHScroll.wCurPos = 0;
  697.       pPictureData->spmsVScroll.wCurPos = 0;
  698.  
  699.         // Set copy option default values
  700.       SetOptionsDefaults( hwndPicture, pPictureData );
  701.  
  702.       if( pPictureData->qtoleOptions.bZoomHalf )
  703.           wZoomIndex = IMAGE_SIZE_50;
  704.       else if( pPictureData->qtoleOptions.bZoomDouble )
  705.           wZoomIndex = IMAGE_SIZE_200;
  706.       else
  707.           wZoomIndex = IMAGE_SIZE_100;
  708.  
  709.    // Build picture. This initializes pPictureData->rcCurPictureRect.
  710.       if( ZoomPicture( hwndPicture, wZoomIndex ))
  711.           goto Failed;  // Error displayed by function
  712.  
  713.    // At this point, the picture is in a window whose size
  714.    // and position is the current MDI default . Now, resize to actual
  715.    // size of picture, without clipping if possible
  716.  
  717.          // Get default corner
  718.       GetWindowRect( hwndPicture, &rcWindow );
  719.       MapWindowPoints( HWND_DESKTOP, ViewerQueryClientWindow(),
  720.                                                 (LPPOINT) &rcWindow, 2 );
  721.       ptCorner = *((LPPOINT) &rcWindow.left);
  722.  
  723.          // Adjust window to fit normal size of picture
  724.       rcWindow = pPictureData->rcCurPictureRect;
  725.          // get client rect from picture rect in client coordinates
  726.       ClientRectFromPicture( &rcWindow );
  727.          // Now adjust for windows stuff
  728.       AdjustWindowRect( &rcWindow,
  729.                        GetWindowLong( hwndPicture, GWL_STYLE ), FALSE );
  730.       wWidth  = rcWindow.right  - rcWindow.left;
  731.       wHeight = rcWindow.bottom - rcWindow.top;
  732.       OffsetRect( &rcWindow, ptCorner.x - rcWindow.left,
  733.                                           ptCorner.y - rcWindow.top );
  734.          // rcWindow now contains the resized window positioned so that
  735.          // the UL corner is at the MDI default position
  736.  
  737.          // Now see if it will fit on screen.
  738.       GetClientRect( ViewerQueryClientWindow(), &rcclientClient );
  739.       if( rcWindow.right > rcclientClient.right )
  740.          {    // extends beyond right border
  741.               // Try to shift it to the left
  742.           nDiff = rcclientClient.right - wWidth;
  743.           rcWindow.left  = max( 0, nDiff );
  744.           rcWindow.right = rcclientClient.right;
  745.          }
  746.  
  747.       if( rcWindow.bottom > rcclientClient.bottom )
  748.          {    // extends beyond bottom
  749.               // Try to shift it up
  750.           nDiff = rcclientClient.bottom - wHeight;
  751.           rcWindow.top    = max( 0, nDiff );
  752.           rcWindow.bottom = rcclientClient.bottom;
  753.          }
  754.  
  755.       MoveWindow( hwndPicture, rcWindow.left, rcWindow.top,
  756.                                  rcWindow.right - rcWindow.left,
  757.                                    rcWindow.bottom - rcWindow.top, TRUE );
  758.  
  759.       SetCursor( hcursorSave );
  760.  
  761.       SetFocus( hwndPicture );
  762.  
  763.         // Tell qtole.dll that the picture wnd has been opened
  764.       if( ( lpOleData = ViewerQueryOleData()) && lpOleData->lpqtoleServer )
  765.          {qtoleOpenWnd.lStructSize  = sizeof( qtoleOpenWnd );
  766.           qtoleOpenWnd.lVersion     = VERSION_1;
  767.           qtoleOpenWnd.wObjectType  = PICTURE_OBJECT;
  768.           qtoleOpenWnd.hwndObject   = hwndPicture;
  769.           qtoleOpenWnd.lpObjectPath = pPictureData->szPicturePath;
  770.           qtoleOpenWnd.lpObjectName = pPictureData->szPictureName;
  771.  
  772.           QTOLE_OpeningNewObjectWnd( lpOleData, &qtoleOpenWnd );
  773.          }
  774.  
  775.       return  0L;
  776.  
  777.  Failed:
  778.       if( hcursorSave )
  779.           SetCursor( hcursorSave );
  780.  
  781.       if( pPictureData->phPicture != NULL)
  782.           DisposePicture( pPictureData->phPicture );
  783.  
  784.       if( pPictureData->hpalPicture )
  785.           DeleteObject( pPictureData->hpalPicture );
  786.  
  787.       SetWindowWord( hwndPicture, 0, 0 );
  788.  
  789.       if( pPictureData )
  790.           LocalUnlock( hPictureData );
  791.       if( hPictureData )
  792.           LocalFree( hPictureData );
  793.  
  794.       return -1;
  795.  
  796.      }
  797.  
  798.  
  799. // Function: CheckDupEnumProc - Checks for duplicate pictures and
  800. //                              fixes up titles if there are any
  801. // --------------------------------------------------------------------
  802. // Parameters: As required by Microsoft Windows
  803. //
  804. // Returns:    Always TRUE;
  805. // --------------------------------------------------------------------
  806.    BOOL __export CALLBACK CheckDupEnumProc( HWND hwnd, LPARAM lParam )
  807.  
  808.    // Look for duplicate pictures. Test is on path rather than just name
  809.  
  810.      {char             szBuffer[50];         // Temp buffer
  811.       HWND             hwndActivePicture;    // Handle of active picture wnd
  812.       NPPICTUREDATA    pPictureData;         // -> enum wnd picture data struct
  813.       NPPICTUREDATA    pActivePictureData;   // -> active wnd picture data struct
  814.  
  815.  
  816.          // skip active picture
  817.       if( ( hwndActivePicture = (HWND) LOWORD( lParam )) == hwnd )
  818.           return TRUE;
  819.  
  820.       if( !GetClassName( hwnd, szBuffer, sizeof( szBuffer )) ||
  821.                               lstrcmpi( szBuffer, VIEWER_PICTURE_CLASS ))
  822.           return TRUE;
  823.  
  824.       pPictureData = (NPPICTUREDATA) GetWindowWord( hwnd, 0 );
  825.       pActivePictureData =
  826.                     (NPPICTUREDATA) GetWindowWord( hwndActivePicture, 0 );
  827.       if( !pPictureData || !pActivePictureData )
  828.           return TRUE;
  829.  
  830.       if( !lstrcmpi( pPictureData->szPicturePath,
  831.                                       pActivePictureData->szPicturePath ))
  832.          {   // Found a duplicate
  833.           g.wPictureCount++;
  834.           if( g.bCreating )
  835.              {if( pPictureData->wDuplicationIndex == 0 )
  836.                  {pPictureData->wDuplicationIndex = 1;
  837.                   wsprintf( szBuffer, "%s:%u",
  838.                                    (LPSTR) pPictureData->szPictureName,
  839.                                          pPictureData->wDuplicationIndex );
  840.                   SetWindowText( hwnd, szBuffer );
  841.                  }
  842.              }
  843.           else
  844.              {if( pPictureData->wDuplicationIndex >
  845.                                   pActivePictureData->wDuplicationIndex )
  846.                  {pPictureData->wDuplicationIndex--;
  847.                   wsprintf( szBuffer, "%s:%u",
  848.                                    (LPSTR) pPictureData->szPictureName,
  849.                                          pPictureData->wDuplicationIndex );
  850.                   SetWindowText( hwnd, szBuffer );
  851.                  }
  852.               if( pPictureData->wDuplicationIndex == 1 )
  853.                   g.hwndFirstDup = hwnd;
  854.              }
  855.  
  856.           if( pPictureData->hwndGetInfo &&
  857.                  !PostMessage( pPictureData->hwndGetInfo,
  858.                                       WM_INFO_UPDATEFILENAME, 0, 0L ))
  859.               SendMessage( pPictureData->hwndGetInfo,
  860.                                         WM_INFO_UPDATEFILENAME, 0, 0L );
  861.          }
  862.  
  863.       return TRUE;
  864.      }
  865.  
  866.  
  867. // Function: ViewerEditCommands - Process WM_COMMAND, Edit popup messages
  868. // --------------------------------------------------------------------
  869. // Parameters: HWND   hwndPicture;    Picture window
  870. //             WORD   wIDItem;        Menu id
  871. //             WORD   wNotifyCode;    notification message
  872. //
  873. // Returns:    LONG   generally 0L
  874. // --------------------------------------------------------------------
  875.    static LONG NEAR ViewerEditCommands
  876.                       (HWND hwndPicture, WPARAM wIDItem, WORD wNotifyCode )
  877.  
  878.      {NPPICTUREDATA  pPictureData;    // -> picture data struct
  879.       HDC            hdc;             // Handle to device context
  880.       HDC            hdcMem;          // Handle to mem device context
  881.       RECT           rcPicture;       // Picture rect
  882.       HBITMAP        hBitmap;         // Handle to bitmap passed to clipboard
  883.       HBITMAP        hSaveBitmap1;    // Temp bitmap handle
  884.       HCURSOR        hcursorSave;     // Saved cursor
  885.       HBRUSH         hbrushSave;      // Prev brush
  886.       DIBHandle      hbmpDIB;         // Handle of DIB bitmap passed to clipboard
  887.       OSErr          oserr;           // Error return from DrawPictureFile
  888.       HPALETTE       hpal;            // Palette handle
  889.       LPQTOLE_OLEDATA  lpOleData;     // -> ole data
  890.       HPALETTE       hpalSave;        // Prev palette
  891.  
  892.  
  893.       if( !( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  894.          {CommonTellUser( ViewerQueryResources(),
  895.                    VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  896.           return 0L;
  897.          }
  898.  
  899.       switch( wIDItem )
  900.         {case VIEWER_EDIT_COPYPICTURE:
  901.             if( IsIconic( hwndPicture ))
  902.                 return 0L;
  903.  
  904.                // If ole, let ole do the copy
  905.             if( ( lpOleData = ViewerQueryOleData()) && lpOleData->lpqtoleServer )
  906.                {PopulateOptionsStruct( hwndPicture, pPictureData );
  907.  
  908.                 QTOLE_Copy( lpOleData, (LPQTOLE_OPTIONS) &pPictureData->qtoleOptions );
  909.  
  910.                   // We must compensate for an error in certain drivers by
  911.                   // resetting the palette back the way we found it
  912.                 if( ViewerIsPalettized() &&
  913.                           pPictureData->hpalPicture && ( hdc = GetDC( hwndPicture )))
  914.                    {hpalSave = SelectPalette( hdc, pPictureData->hpalPicture, 0 );
  915.                     RealizePalette( hdc );
  916.  
  917.                     SelectPalette( hdc, hpalSave, 0 );
  918.                     ReleaseDC( hwndPicture, hdc );
  919.                    }
  920.                }
  921.             else     // No ole so do copy here
  922.                {if( !( hdc = GetDC( hwndPicture )))
  923.                    {CommonTellUser( ViewerQueryResources(),
  924.                                     VIEWER_STRING_NODC,
  925.                                     VIEWER_STRING_CAPTION, MB_OK );
  926.                     return 0L;
  927.                    }
  928.  
  929.                 rcPicture.left = rcPicture.top = 0;
  930.                 rcPicture.right  = pPictureData->idImageInfo.width;
  931.                 rcPicture.bottom = pPictureData->idImageInfo.height;
  932.  
  933.                 if( !( hBitmap = CreateCompatibleBitmap
  934.                                   ( hdc, rcPicture.right, rcPicture.bottom )))
  935.                    {CommonTellUser( ViewerQueryResources(),
  936.                                     VIEWER_STRING_COPYFAILED,
  937.                                     VIEWER_STRING_CAPTION, MB_OK );
  938.                     ReleaseDC( hwndPicture, hdc );
  939.                     return 0L;
  940.                    }
  941.  
  942.                 oserr = 1L;   // initialize to nonzero value
  943.                 if( (hdcMem = CreateCompatibleDC( hdc )) &&
  944.                            ( hSaveBitmap1 = SelectObject( hdcMem, hBitmap )))
  945.                    {hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  946.                     hbrushSave = SelectObject( hdcMem, PICBACKGRNDBRUSH );
  947.                     oserr = DrawPicture( hdcMem, pPictureData->phPicture,
  948.                                                        &rcPicture, NULL );
  949.                     SetCursor( hcursorSave );
  950.  
  951.                        // Unselect the bitmap and brush
  952.                     SelectObject( hdcMem, hSaveBitmap1 );
  953.                     if( hbrushSave )
  954.                         SelectObject( hdcMem, hbrushSave );
  955.  
  956.                     if( !oserr )
  957.                        {OpenClipboard( hwndPicture );
  958.                         EmptyClipboard();
  959.                           // Give bitmap to clipboard if OK
  960.                         if( !SetClipboardData( CF_BITMAP, hBitmap ))
  961.                            DeleteObject( hBitmap );
  962.  
  963.                           // Now add palette if there is one
  964.                         if( ( hpal = GetPicturePalette( pPictureData->phPicture )) &&
  965.                                          !SetClipboardData( CF_PALETTE, hpal ))
  966.                             DeleteObject( hpal );
  967.  
  968.                           // Now try to add DIBitmap to clipboard
  969.                         if( ( hbmpDIB =
  970.                                PictureToDIB( pPictureData->phPicture )) &&
  971.                                          !SetClipboardData( CF_DIB, hbmpDIB ))
  972.                             GlobalFree( hbmpDIB );
  973.  
  974.                         CloseClipboard();
  975.                        }
  976.                    }
  977.                 else
  978.                    {if( hBitmap )
  979.                        DeleteObject( hBitmap );
  980.                    }
  981.  
  982.                 if( oserr )
  983.                     CommonTellUser( ViewerQueryResources(),
  984.                                         VIEWER_STRING_DRAWPICFAIL,
  985.                                                 VIEWER_STRING_CAPTION, MB_OK );
  986.                 if( hdcMem )
  987.                     DeleteDC( hdcMem );
  988.  
  989.                 ReleaseDC( hwndPicture, hdc );
  990.                }
  991.  
  992.             return 0L;
  993.  
  994.          case VIEWER_EDIT_OPTIONS:
  995.             PopulateOptionsStruct( hwndPicture, pPictureData );
  996.  
  997.             if( ViewerGetOptions( hwndPicture, &pPictureData->qtoleOptions ))
  998.                UpdatePictForOptions( hwndPicture, pPictureData, FALSE );
  999.  
  1000.             return 0L;
  1001.  
  1002.          case VIEWER_EDIT_CANCELSEL:
  1003.             if( !IsRectEmpty( &pPictureData->qtoleOptions.rcSelection ) &&
  1004.                                                 ( hdc = GetDC( hwndPicture )))
  1005.                {DrawSelectionRect( hwndPicture, hdc, pPictureData );
  1006.                 ReleaseDC( hwndPicture, hdc );
  1007.                 SetRectEmpty( &pPictureData->qtoleOptions.rcSelection );
  1008.                }
  1009.  
  1010.             return 0L;
  1011.         }
  1012.  
  1013.       return 0L;      // should never get here
  1014.  
  1015.      }
  1016.  
  1017.  
  1018. // Function: InitSelection - Initiates the selection
  1019. // --------------------------------------------------------------------
  1020. // Parameters: HWND          hwndPicture      Handle of picture wnd
  1021. //             POINT         ptCursor         Cursor position
  1022. //
  1023. // Returns:    BOOL          TRUE if OK
  1024. // --------------------------------------------------------------------
  1025.    static BOOL NEAR InitSelection( HWND hwndPicture, POINT ptCursor )
  1026.  
  1027.      {NPPICTUREDATA     pPictureData;
  1028.       HDC               hdc;
  1029.  
  1030.           // First remove old selection
  1031.       if( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))
  1032.          {g.rcSelection = pPictureData->qtoleOptions.rcSelection;
  1033.           if( !IsRectEmpty( &g.rcSelection ) &&
  1034.                                     ( hdc = GetDC( hwndPicture )))
  1035.              {DrawSelectionRect( hwndPicture, hdc, pPictureData );
  1036.               ReleaseDC( hwndPicture, hdc );
  1037.              }
  1038.          }
  1039.  
  1040.       if( hdc = GetDC( NULL ))
  1041.          {ClientToScreen( hwndPicture, &ptCursor );
  1042.  
  1043.           *(LPPOINT) &g.rcSelection.left  = ptCursor;
  1044.           *(LPPOINT) &g.rcSelection.right = ptCursor;
  1045.  
  1046.           DrawFocusRect( hdc, &g.rcSelection );
  1047.  
  1048.           ReleaseDC( NULL, hdc );
  1049.  
  1050.           return TRUE;
  1051.          }
  1052.  
  1053.       return FALSE;
  1054.      }
  1055.  
  1056. // Function: MoveTheSelectRect - Move the selection rect
  1057. // --------------------------------------------------------------------
  1058. // Parameters: HWND          hwndPicture      Handle of picture wnd
  1059. //             POINT         ptCursor         Cursor position
  1060. //
  1061. // Returns:    VOID
  1062. // --------------------------------------------------------------------
  1063.    static VOID NEAR MoveTheSelectRect( HWND hwndPicture, POINT ptCursor )
  1064.  
  1065.      {HDC       hdc;
  1066.  
  1067.       if( hdc = GetDC( NULL ))
  1068.          {ClientToScreen( hwndPicture, &ptCursor );
  1069.           DrawFocusRect( hdc, &g.rcSelection );
  1070.  
  1071.           *(LPPOINT) &g.rcSelection.right = ptCursor;
  1072.           if( g.rcSelection.right < g.rcSelection.left )
  1073.                g.rcSelection.right = g.rcSelection.left;
  1074.  
  1075.           if( g.rcSelection.bottom < g.rcSelection.top )
  1076.                g.rcSelection.bottom = g.rcSelection.top;
  1077.  
  1078.           DrawFocusRect( hdc, &g.rcSelection );
  1079.  
  1080.           ReleaseDC( NULL, hdc );
  1081.          }
  1082.  
  1083.       return;
  1084.      }
  1085.  
  1086. // Function: EndTheSelection - End the selection
  1087. // --------------------------------------------------------------------
  1088. // Parameters: HWND          hwndPicture      Handle of picture wnd
  1089. //
  1090. // Returns:    VOID
  1091. // --------------------------------------------------------------------
  1092.    static VOID NEAR EndTheSelection( HWND hwndPicture )
  1093.  
  1094.      {NPPICTUREDATA     pPictureData;
  1095.       int               nZoomMult;
  1096.       HDC               hdc;
  1097.  
  1098.          // Remove selection rect here and redraw later using function
  1099.          // This is necessary because roundoff in convertions can cause
  1100.          // one pixel differences in rect coordinates
  1101.       if( hdc = GetDC( NULL ))
  1102.          {DrawFocusRect( hdc, &g.rcSelection );
  1103.           ReleaseDC( NULL, hdc );
  1104.          }
  1105.  
  1106.       if( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))
  1107.          {if( !IsRectEmpty( &g.rcSelection ))
  1108.              {MapWindowPoints( HWND_DESKTOP, hwndPicture,
  1109.                                             (LPPOINT) &g.rcSelection, 2 );
  1110.  
  1111.               ClientToPicture( (LPPOINT) &g.rcSelection, 2 );
  1112.                 // rcCurPictureRect knows about scroll offsets.
  1113.                 // These offsets are negative
  1114.               OffsetRect( &g.rcSelection,
  1115.                                -pPictureData->rcCurPictureRect.left,
  1116.                                           -pPictureData->rcCurPictureRect.top );
  1117.  
  1118.                 // Now convert to 100% zoom.  rcSelection will be stored
  1119.                 // at 100% zoom. Copy will reflect actual zoom
  1120.               nZoomMult = (int) ViewerQueryZoomMultiplier
  1121.                              ( pPictureData->zsZoomScroll.wCurZoomIndex );
  1122.               g.rcSelection.left   = MulDiv( g.rcSelection.left,   100, nZoomMult );
  1123.               g.rcSelection.top    = MulDiv( g.rcSelection.top,    100, nZoomMult );
  1124.               g.rcSelection.right  = MulDiv( g.rcSelection.right,  100, nZoomMult );
  1125.               g.rcSelection.bottom = MulDiv( g.rcSelection.bottom, 100, nZoomMult );
  1126.  
  1127.                 // Now check that section is inside picture
  1128.               if( g.rcSelection.left < 0 )
  1129.                   g.rcSelection.left = 0;
  1130.               if( g.rcSelection.top < 0 )
  1131.                   g.rcSelection.top = 0;
  1132.               if( g.rcSelection.right > (int) pPictureData->idImageInfo.width )
  1133.                   g.rcSelection.right = pPictureData->idImageInfo.width;
  1134.               if( g.rcSelection.bottom > (int) pPictureData->idImageInfo.height )
  1135.                   g.rcSelection.bottom = pPictureData->idImageInfo.height;
  1136.                 // g.rcSelection now has selection relative to UL corner
  1137.                 // of picture at 100% zoom
  1138.              }
  1139.  
  1140.           pPictureData->qtoleOptions.rcSelection = g.rcSelection;
  1141.  
  1142.              // Now redraw the rect to leave it visible
  1143.           if( hdc = GetDC( hwndPicture ))
  1144.              {DrawSelectionRect( hwndPicture, hdc, pPictureData );
  1145.               ReleaseDC( hwndPicture, hdc );
  1146.              }
  1147.          }
  1148.  
  1149.  
  1150.       return;
  1151.      }
  1152.  
  1153.  
  1154. // Function: ViewerImageCommands - Process WM_COMMAND, Image popup messages
  1155. // --------------------------------------------------------------------
  1156. // Parameters: HWND   hwndPicture;    Picture window
  1157. //             WORD   wIDItem;        Menu id
  1158. //             WORD   wNotifyCode;    notification message
  1159. //
  1160. // Returns:    LONG   generally 0L
  1161. // --------------------------------------------------------------------
  1162.    static LONG NEAR ViewerImageCommands
  1163.                       (HWND hwndPicture, WPARAM wIDItem, WORD wNotifyCode )
  1164.  
  1165.      {DLGPROC        lpDlgProc;        // -> dlg callback proc
  1166.       HWND           hInfoDialog;      // Handle to modeless info dialog
  1167.       NPPICTUREDATA  pPictureData;     // -> picture data struct
  1168.  
  1169.       if( !(pPictureData =
  1170.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  1171.          {CommonTellUser( ViewerQueryResources(),
  1172.                    VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  1173.           return 0L;
  1174.          }
  1175.  
  1176.       switch( wIDItem )
  1177.         {case VIEWER_IMAGE_GETINFO:
  1178.             if( pPictureData->hwndGetInfo )
  1179.                {SetFocus( pPictureData->hwndGetInfo );
  1180.                }
  1181.             else if( !(lpDlgProc = (DLGPROC) MakeProcInstance
  1182.                      ( (FARPROC) GetInfoDlgProc, ViewerQueryInstance())) ||
  1183.                   !( hInfoDialog = CreateDialog( ViewerQueryResources(),
  1184.                                 MAKEINTRESOURCE( VIEWER_DLG_GETINFO ),
  1185.                                   ViewerQueryFrameWindow(), lpDlgProc )))
  1186.                {CommonTellUser( ViewerQueryResources(),
  1187.                                    VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  1188.                }
  1189.  
  1190.             return 0L;
  1191.  
  1192.          case VIEWER_IMAGE_HALFSIZE:
  1193.          case VIEWER_IMAGE_NORMALSIZE:
  1194.          case VIEWER_IMAGE_DOUBLESIZE:
  1195.                 // errors reported by function
  1196.             ZoomPicture( hwndPicture, wIDItem );
  1197.             return 0L;
  1198.         }
  1199.  
  1200.       return 0L;      // should never get here
  1201.  
  1202.      }
  1203.  
  1204.  
  1205. // Function: PaintThePicture - processes the WM_PAINT message when normal
  1206. // --------------------------------------------------------------------
  1207. // Parameters: HWND         hwndPicture     Handle of Picture window
  1208. //
  1209. // Returns:    LONG         0L if successful
  1210. // --------------------------------------------------------------------
  1211.    static LONG NEAR PaintThePicture( HWND hwndPicture )
  1212.  
  1213.      {PAINTSTRUCT     ps;               // Paint struct
  1214.       NPPICTUREDATA   pPictureData;     // -> picture data struct
  1215.       HCURSOR         hcursorSave;      // Save cursor handle
  1216.       HBRUSH          hbrushSave;       // Prev brush
  1217.       RECT            rcclientPicture;  // Picture rect in client coordinates
  1218.       int             nRegion;          // Return from IntersectClipRegion
  1219.       OSErr           oserr;            // DrawPicture error return
  1220.       WORD            wIDError;         // Error message ID
  1221.  
  1222.  
  1223.       if( !( pPictureData =
  1224.                        (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  1225.          {if( BeginPaint( hwndPicture, &ps ))
  1226.              EndPaint( hwndPicture, &ps );
  1227.           return 0L;
  1228.          }
  1229.  
  1230.          // Always paint the grow box. This must come before BeginPaint
  1231.       InvalidateRect( hwndPicture, &pPictureData->rcGrowBox, FALSE );
  1232.  
  1233.       if( !BeginPaint( hwndPicture, &ps ))
  1234.          {CommonTellUser( ViewerQueryResources(),
  1235.                           VIEWER_STRING_NOMEMORY,
  1236.                           VIEWER_STRING_CAPTION, MB_OK );
  1237.           return VIEWER_STRING_NOMEMORY;
  1238.          }
  1239.  
  1240.    // First draw the grow box and exclude the rect so that picture isn't
  1241.    // draw over it below
  1242.       PaintTheGrowBox( hwndPicture, ps.hdc, pPictureData );
  1243.       ExcludeClipRect( ps.hdc, pPictureData->rcGrowBox.left,
  1244.                                pPictureData->rcGrowBox.top,
  1245.                                pPictureData->rcGrowBox.right,
  1246.                                pPictureData->rcGrowBox.bottom );
  1247.  
  1248.    // Note: rcCurPictureRect knows about scrolling offset. left and
  1249.    // top are negative if pict is scrolled. (0,0) is always the UL
  1250.    // corner of the displayed portion of the picture in picture
  1251.    // coordinates.
  1252.  
  1253.       rcclientPicture = pPictureData->rcCurPictureRect;
  1254.  
  1255.    // Convert to client coordinates since ps.hdc understands client
  1256.    // coordinates
  1257.       PictureToClient( (LPPOINT) &rcclientPicture, 2 );
  1258.  
  1259.     // Paint the background
  1260.       hbrushSave = SelectObject( ps.hdc, PICBACKGRNDBRUSH );
  1261.       SaveDC( ps.hdc );
  1262.       ExcludeClipRect( ps.hdc, rcclientPicture.left, rcclientPicture.top,
  1263.                             rcclientPicture.right, rcclientPicture.bottom );
  1264.       FillRect( ps.hdc, &ps.rcPaint, PICBACKGRNDBRUSH );
  1265.       RestoreDC( ps.hdc, -1 );
  1266.       if( hbrushSave )
  1267.           SelectObject( ps.hdc, hbrushSave );
  1268.  
  1269.    // Check if picture needs to be painted
  1270.       SaveDC( ps.hdc );
  1271.       nRegion = IntersectClipRect( ps.hdc,
  1272.                 rcclientPicture.left, rcclientPicture.top,
  1273.                     rcclientPicture.right, rcclientPicture.bottom );
  1274.       if( ( nRegion == ERROR ) || ( nRegion == NULLREGION ))
  1275.          {RestoreDC( ps.hdc, -1 );
  1276.           EndPaint( hwndPicture, &ps );
  1277.           return 0L;
  1278.          }
  1279.  
  1280.    // Draw picture
  1281.       hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  1282.  
  1283.       if( oserr = DrawPicture( ps.hdc, pPictureData->phPicture,
  1284.                                              &rcclientPicture, NULL ))
  1285.          {if( oserr == insufficientMemory )
  1286.              wIDError = VIEWER_STRING_NOMEMORY;
  1287.           else
  1288.              wIDError = VIEWER_STRING_DRAWPICFAIL;
  1289.  
  1290.           CommonTellUser( ViewerQueryResources(), wIDError,
  1291.                                    VIEWER_STRING_CAPTION, MB_OK );
  1292.  
  1293.             // Validate rect to prevent infinite loop
  1294.           ValidateRect( hwndPicture, NULL );
  1295.           SetCursor( hcursorSave );
  1296.           RestoreDC( ps.hdc, -1 );
  1297.           EndPaint( hwndPicture, &ps );
  1298.  
  1299.           return VIEWER_STRING_DRAWPICFAIL;
  1300.          }
  1301.       RestoreDC( ps.hdc, -1 );
  1302.  
  1303.       if( !IsRectEmpty( &pPictureData->qtoleOptions.rcSelection ))
  1304.           DrawSelectionRect( hwndPicture, ps.hdc, pPictureData );
  1305.  
  1306.       SetCursor( hcursorSave );
  1307.  
  1308.    // Done painting
  1309.       EndPaint( hwndPicture, &ps );
  1310.  
  1311.       return 0L;
  1312.      }
  1313.  
  1314.  
  1315. // Function: DrawSelectionRect - Draws the selection rect
  1316. // --------------------------------------------------------------------
  1317. // Parameters: HWND            hwndPicture    HWND of picture wnd
  1318. //             HDC             hdc            HDC of picture wnd
  1319. //             NPPICTUREDATA   pPictureData
  1320. //
  1321. // Returns:    VOID
  1322. // --------------------------------------------------------------------
  1323.    static VOID NEAR DrawSelectionRect
  1324.                    ( HWND hwndPicture, HDC hdc, NPPICTUREDATA pPictureData )
  1325.  
  1326.      {RECT       rcSelection;
  1327.       RECT       rcPicture;
  1328.       int        nZoomMult;
  1329.       int        nRegion;
  1330.  
  1331.          // Get picture rect and prevent drawing outside the picture
  1332.       GetClientRect( hwndPicture, &rcPicture );
  1333.       PictureRectFromClient( &rcPicture );
  1334.  
  1335.       nRegion = IntersectClipRect( hdc,
  1336.                           rcPicture.left, rcPicture.top,
  1337.                               rcPicture.right, rcPicture.bottom );
  1338.       if( ( nRegion == ERROR ) || ( nRegion == NULLREGION ))
  1339.           return;
  1340.  
  1341.           // Convert to current zoom
  1342.       rcSelection = pPictureData->qtoleOptions.rcSelection;
  1343.       nZoomMult = (int) ViewerQueryZoomMultiplier
  1344.                        ( pPictureData->zsZoomScroll.wCurZoomIndex );
  1345.       rcSelection.left   = MulDiv( rcSelection.left,   nZoomMult, 100 );
  1346.       rcSelection.top    = MulDiv( rcSelection.top,    nZoomMult, 100 );
  1347.       rcSelection.right  = MulDiv( rcSelection.right,  nZoomMult, 100 );
  1348.       rcSelection.bottom = MulDiv( rcSelection.bottom, nZoomMult, 100 );
  1349.  
  1350.           // Offset for current scroll and convert to client coordinates
  1351.       OffsetRect( &rcSelection,
  1352.                       pPictureData->rcCurPictureRect.left,
  1353.                                      pPictureData->rcCurPictureRect.top );
  1354.       PictureToClient( (LPPOINT) &rcSelection, 2 );
  1355.  
  1356.       DrawFocusRect( hdc, &rcSelection );
  1357.  
  1358.       return;
  1359.      }
  1360.  
  1361. // Function: PaintTheIcon - processes the WM_PAINT message when iconic
  1362. // --------------------------------------------------------------------
  1363. // Parameters: HWND         hwndPicture     Handle of Picture window
  1364. //
  1365. // Returns:    LONG         0L
  1366. // --------------------------------------------------------------------
  1367.    static LONG NEAR PaintTheIcon( HWND hwndPicture )
  1368.  
  1369.      {PAINTSTRUCT        ps;              // Paint struct
  1370.       NPPICTUREDATA      pPictureData;    // -> picture data struct
  1371.       HDC                hmemDC;          // Memory DC
  1372.       HBITMAP            hbitmapSave;     // Prev bitmap
  1373.       BITMAP             bm;              // Bitmap struct
  1374.       LPBITMAPINFOHEADER lpbmih;          // -> bitmapinfo header struct
  1375.       HPALETTE           hpalSave;        // Prev palette
  1376.       HBRUSH             hbrush;          // Background brush
  1377.  
  1378.       static RECT        rcPic =
  1379.                          {4, 4, 32, 32};  // Rect used in painting pic
  1380.  
  1381.  
  1382.       InvalidateRect( hwndPicture, NULL, FALSE );
  1383.  
  1384.       if( !BeginPaint( hwndPicture, &ps ))
  1385.           return 0L;
  1386.  
  1387.       if( !( pPictureData = (NPPICTUREDATA)
  1388.                        GetWindowWord( hwndPicture, 0 )) ||
  1389.                 ( !pPictureData->lpDIBIconMem && !pPictureData->hbitmapIcon ))
  1390.          {if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE )))
  1391.              {FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1392.               DeleteObject( hbrush );
  1393.              }
  1394.  
  1395.           if( g.hpictIcon )
  1396.               DrawIcon( ps.hdc, 2, 2, g.hpictIcon );
  1397.           EndPaint( hwndPicture, &ps );
  1398.           return 0L;
  1399.          }
  1400.  
  1401.           // Will have DIB icon only if palettized
  1402.       if( pPictureData->lpDIBIconMem )
  1403.          {lpbmih = (LPBITMAPINFOHEADER) pPictureData->lpDIBIconMem;
  1404.  
  1405.              // Select the current system palette into the dc so SetDIBits..
  1406.              // can do color matching. The system palette is set by the last
  1407.              // call to RealizePalette and so the current palette will
  1408.              // match the picture's palette only if the picture is active
  1409.           hpalSave = SelectPalette( ps.hdc, g.hpalCurrentSystem, FALSE );
  1410.  
  1411.           SetDIBitsToDevice( ps.hdc, rcPic.left, rcPic.top,
  1412.                     (WORD) lpbmih->biWidth, (WORD) lpbmih->biHeight,
  1413.                     0, 0, 0, (WORD) lpbmih->biHeight,
  1414.                     (LPVOID) ((LPSTR) lpbmih +
  1415.                                  (WORD) lpbmih->biSize + SIZE_COLOR_TABLE ),
  1416.                     pPictureData->lpDIBIconMem, DIB_RGB_COLORS );
  1417.  
  1418.           if( hpalSave )
  1419.               SelectPalette( ps.hdc, hpalSave, FALSE );
  1420.  
  1421.             // Now paint the background
  1422.           SaveDC( ps.hdc );
  1423.           ExcludeClipRect( ps.hdc, rcPic.left, rcPic.top,
  1424.                                              rcPic.right, rcPic.bottom );
  1425.             // COLOR_APPWORKSPACE is standard MDI background color
  1426.           if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE )))
  1427.              {FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1428.               DeleteObject( hbrush );
  1429.              }
  1430.           RestoreDC( ps.hdc, -1 );
  1431.  
  1432.             // Now draw the picture frame
  1433.           if( g.hpictIcon )
  1434.               DrawIcon( ps.hdc, 2, 2, g.hpictIcon );
  1435.          }
  1436.       else
  1437.          {hmemDC = NULL;
  1438.           if( pPictureData->hbitmapIcon &&
  1439.                 ( hmemDC = CreateCompatibleDC( ps.hdc )) &&
  1440.                    ( hbitmapSave =
  1441.                          SelectObject( hmemDC, pPictureData->hbitmapIcon )))
  1442.              {GetObject( pPictureData->hbitmapIcon, sizeof( BITMAP ), &bm );
  1443.  
  1444.               BitBlt( ps.hdc, 0, 0, bm.bmWidth, bm.bmHeight,
  1445.                                                  hmemDC, 0, 0, SRCCOPY );
  1446.               SelectObject( hmemDC, hbitmapSave );
  1447.              }
  1448.           else
  1449.              {if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE )))
  1450.                  {FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1451.                   DeleteObject( hbrush );
  1452.                  }
  1453.  
  1454.               if( g.hpictIcon )
  1455.                   DrawIcon( ps.hdc, 2, 2, g.hpictIcon );
  1456.              }
  1457.  
  1458.           if( hmemDC )
  1459.               DeleteDC( hmemDC );
  1460.          }
  1461.  
  1462.       EndPaint( hwndPicture, &ps );
  1463.  
  1464.       return 0L;
  1465.  
  1466.      }
  1467.  
  1468. // Function: BuildIconBitmap - builds the icon bitmap
  1469. // --------------------------------------------------------------------
  1470. // Parameters: HWND            hwndPicture     Handle of picture wnd
  1471. //             NPPICTUREDATA   pPictureData    -> picture data struct
  1472. //
  1473. // Returns:    LONG         0L
  1474. // --------------------------------------------------------------------
  1475.    static BOOL NEAR BuildIconBitmap
  1476.                               ( HWND hwndPicture, NPPICTUREDATA pPictureData )
  1477.  
  1478.      {HDC              hdc;                // DC of picture
  1479.       HDC              hmemDC;             // Memory dc
  1480.       HBRUSH           hbrush;             // Temp background brush
  1481.       HBRUSH           hbrushSave;         // Prev brush
  1482.       HBITMAP          hbitmapSave;        // Prev bitmap
  1483.       HBITMAP          hbitmap;            // Handle of icon bitmap
  1484.       HGLOBAL          hbmi;               // Memory handle for DIB info struct
  1485.       HGLOBAL          hnewbmi;            // Temp memory handle
  1486.       BITMAPINFOHEADER bi;                 // Bitmap info header struct
  1487.       LPVOID           lpbmi;              // -> bitmap info struct
  1488.       BITMAP           bm;                 // BITMAP struct
  1489.       HPALETTE         hpalSave;           // Prev palette
  1490.       HCURSOR          hcursorSave;        // Prev cursor
  1491.       RECT             rcPicRect;          // Picture rect
  1492.       WORD             wIconBmpWidth;      // Icon width
  1493.       WORD             wIconBmpHeight;     // Icon height
  1494.       WORD             wProportional;      // Temp
  1495.  
  1496.       static RECT      rcIcon =
  1497.                           {2, 2, 34, 34};  // Rect used in painting icon
  1498.       static RECT      rcPicbmp =
  1499.                           {4, 4, 32, 32};  // Rect used in painting pic
  1500.       static RECT      rcPicdib =
  1501.                           {0, 0, 28, 28};  // Rect used in painting pic
  1502.       static RECT      rcBitmap =          // Overall bitmap dimensions
  1503.                           {0, 0, 36, 36 };
  1504.  
  1505.  
  1506.             // Macro used to align on ULONG boundary
  1507.             // From 3.1 SDK sample code, dib.h
  1508.   #define WIDTHBYTES(i)  ( ( i + 31 ) / 32 * 4 )
  1509.  
  1510.       pPictureData->hbitmapIcon  = NULL;
  1511.       pPictureData->lpDIBIconMem = NULL;
  1512.  
  1513.       if( !( hdc = GetDC( hwndPicture )))
  1514.          {return FALSE;
  1515.          }
  1516.  
  1517.       if( !( hmemDC = CreateCompatibleDC( hdc )))
  1518.          {ReleaseDC( hwndPicture, hdc );
  1519.           return FALSE;
  1520.          }
  1521.  
  1522.       hbitmap  = NULL;
  1523.       hpalSave = NULL;
  1524.       hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  1525.  
  1526.             // Get picture rect with proportions of the original pic
  1527.       rcPicRect = rcPicbmp;
  1528.       wIconBmpWidth  = rcPicbmp.right - rcPicbmp.left;
  1529.       wIconBmpHeight = rcPicbmp.bottom - rcPicbmp.top;
  1530.       if( pPictureData->idImageInfo.width >
  1531.                                pPictureData->idImageInfo.height )
  1532.          {wProportional = MulDiv( wIconBmpHeight,
  1533.                                  pPictureData->idImageInfo.width,
  1534.                                        pPictureData->idImageInfo.height );
  1535.           rcPicRect.left  -= ( wProportional - wIconBmpWidth ) / 2;
  1536.           rcPicRect.right = rcPicRect.left + wProportional;
  1537.          }
  1538.       else if( pPictureData->idImageInfo.width <
  1539.                                pPictureData->idImageInfo.height )
  1540.          {wProportional = MulDiv( wIconBmpWidth,
  1541.                                  pPictureData->idImageInfo.height,
  1542.                                        pPictureData->idImageInfo.width );
  1543.           rcPicRect.top   -= ( wProportional - wIconBmpHeight ) / 2;
  1544.           rcPicRect.bottom = rcPicRect.top + wProportional;
  1545.          }
  1546.  
  1547.       if( ( hbitmap = CreateCompatibleBitmap( hdc,
  1548.                                 rcBitmap.right, rcBitmap.bottom )) &&
  1549.                          ( hbitmapSave = SelectObject( hmemDC, hbitmap )))
  1550.          {   //First fill the background
  1551.           if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE )))
  1552.             {FillRect( hmemDC, &rcBitmap, hbrush );
  1553.              DeleteObject( hbrush );
  1554.             }
  1555.  
  1556.              // Now draw the picture.
  1557.              // Keep picture inside the allowed rect
  1558.           SaveDC( hmemDC );
  1559.           IntersectClipRect( hmemDC, rcPicbmp.left, rcPicbmp.top,
  1560.                                          rcPicbmp.right, rcPicbmp.bottom );
  1561.  
  1562.           hbrushSave = SelectObject( hmemDC, PICBACKGRNDBRUSH );
  1563.           if( DrawPicture( hmemDC, pPictureData->phPicture, &rcPicRect, NULL ))
  1564.              {CommonTellUser( ViewerQueryResources(),
  1565.                           VIEWER_STRING_DRAWPICFAIL,
  1566.                           VIEWER_STRING_CAPTION, MB_OK );
  1567.              }
  1568.           SelectObject( hmemDC, hbrushSave );
  1569.           RestoreDC( hmemDC, -1 );
  1570.  
  1571.              // Now draw the picture frame
  1572.           if( g.hpictIcon )
  1573.               DrawIcon( hmemDC, 2, 2, g.hpictIcon );
  1574.  
  1575.           SelectObject( hmemDC, hbitmapSave );
  1576.  
  1577.           pPictureData->hbitmapIcon = hbitmap;
  1578.           hbitmap = NULL;
  1579.          }
  1580.       else
  1581.          {goto IconFailed;
  1582.          }
  1583.  
  1584.  
  1585.       if( ViewerIsPalettized())   // Palettized, use DIB bitmap, but only for picture
  1586.          {   // Should always be a palette but test anyway
  1587.           if( pPictureData->hpalPicture &&
  1588.                     !( hpalSave = SelectPalette
  1589.                                   ( hdc, pPictureData->hpalPicture, FALSE )))
  1590.              {CommonTellUser( ViewerQueryResources(),
  1591.                                   VIEWER_STRING_SELPALFAILED, NULL, MB_OK );
  1592.               goto IconFailed;
  1593.              }
  1594.  
  1595.              // Need to offset rcPicRect because of differences btwn
  1596.              // the origins of rcPicbmp and rcPicdib; ( 4, 4) vs ( 0, 0)
  1597.           OffsetRect( &rcPicRect, -rcPicbmp.left, -rcPicbmp.top );
  1598.  
  1599.           if( ( hbitmap = CreateCompatibleBitmap( hdc,
  1600.                                        rcPicdib.right, rcPicdib.bottom )) &&
  1601.                          ( hbitmapSave = SelectObject( hmemDC, hbitmap )))
  1602.              {hbrushSave = SelectObject( hmemDC, PICBACKGRNDBRUSH );
  1603.               if( DrawPicture( hmemDC, pPictureData->phPicture,
  1604.                                                        &rcPicRect, NULL ))
  1605.                  {CommonTellUser( ViewerQueryResources(),
  1606.                           VIEWER_STRING_DRAWPICFAIL,
  1607.                           VIEWER_STRING_CAPTION, MB_OK );
  1608.                   SelectObject( hmemDC, hbitmapSave );
  1609.                   SelectObject( hmemDC, hbrushSave );
  1610.                   goto IconFailed;
  1611.                  }
  1612.               SelectObject( hmemDC, hbrushSave );
  1613.               SelectObject( hmemDC, hbitmapSave );
  1614.              }
  1615.           else
  1616.              {goto IconFailed;
  1617.              }
  1618.  
  1619.              // Now convert to DIB bitmap
  1620.              // Initialize bitmap info header struct
  1621.           GetObject( hbitmap, sizeof( BITMAP ), &bm );
  1622.  
  1623.           bi.biSize          = sizeof( BITMAPINFOHEADER );
  1624.           bi.biWidth         = bm.bmWidth;
  1625.           bi.biHeight        = bm.bmHeight;
  1626.           bi.biPlanes        = 1;
  1627.           bi.biBitCount      = bm.bmPlanes * bm.bmBitsPixel;
  1628.           bi.biCompression   = BI_RGB;
  1629.           bi.biSizeImage     = 0;
  1630.           bi.biXPelsPerMeter = 0;
  1631.           bi.biYPelsPerMeter = 0;
  1632.           bi.biClrUsed       = 0;
  1633.           bi.biClrImportant  = 0;
  1634.  
  1635.           if( !( hbmi = GlobalAlloc( GHND, bi.biSize + SIZE_COLOR_TABLE )))
  1636.              {CommonTellUser( ViewerQueryResources(),
  1637.                                     VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  1638.               goto IconFailed;
  1639.              }
  1640.           lpbmi = (LPVOID) GlobalLock( hbmi );
  1641.  
  1642.              // First get bitmap size by using NULL argument
  1643.           *(LPBITMAPINFOHEADER) lpbmi = bi;
  1644.           GetDIBits( hdc, hbitmap, 0, bm.bmHeight, NULL,
  1645.                                (LPBITMAPINFO) lpbmi, DIB_RGB_COLORS );
  1646.           bi = *(LPBITMAPINFOHEADER) lpbmi;
  1647.              // If driver failed to set size, make a guess
  1648.           if( bi.biSizeImage == 0 )
  1649.               bi.biSizeImage = bi.biHeight *
  1650.                         WIDTHBYTES( (DWORD) bm.bmWidth * bi.biBitCount );
  1651.  
  1652.              // Now realloc to get space for bitmap bits
  1653.           GlobalUnlock( hbmi );
  1654.           if( !( hnewbmi = GlobalReAlloc( hbmi,
  1655.                  bi.biSize + SIZE_COLOR_TABLE + bi.biSizeImage, GHND )))
  1656.              {CommonTellUser( ViewerQueryResources(),
  1657.                                     VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  1658.               GlobalFree( hbmi );
  1659.               goto IconFailed;
  1660.              }
  1661.           hbmi = hnewbmi;
  1662.           lpbmi = (LPVOID) GlobalLock( hbmi );
  1663.  
  1664.              // Now get bitmap bits
  1665.           if( bm.bmHeight != GetDIBits( hdc, hbitmap, 0, bm.bmHeight,
  1666.               (LPVOID)((LPSTR) lpbmi + (WORD) bi.biSize + SIZE_COLOR_TABLE ),
  1667.                               (LPBITMAPINFO) lpbmi, DIB_RGB_COLORS ))
  1668.              {CommonTellUser( ViewerQueryResources(),
  1669.                                   VIEWER_STRING_NOMAKEDIB, NULL, MB_OK );
  1670.               GlobalUnlock( hbmi );
  1671.               GlobalFree( hbmi );
  1672.               goto IconFailed;
  1673.              }
  1674.  
  1675.             // Done. Save -> to DIB and toss device dependent bitmap
  1676.           pPictureData->lpDIBIconMem = (LPBITMAPINFO) lpbmi;
  1677.           DeleteObject( pPictureData->hbitmapIcon );
  1678.           pPictureData->hbitmapIcon  = NULL;
  1679.  
  1680.           DeleteObject( hbitmap );
  1681.           SelectPalette( hdc, hpalSave, FALSE );
  1682.          }
  1683.  
  1684.       SetCursor( hcursorSave );
  1685.       ReleaseDC( hwndPicture, hdc );
  1686.       DeleteDC ( hmemDC );
  1687.  
  1688.       return TRUE;
  1689.  
  1690.   IconFailed:
  1691.       if( hcursorSave )
  1692.           SetCursor( hcursorSave );
  1693.       if( hpalSave )
  1694.           SelectPalette( hdc, hpalSave, FALSE );
  1695.       if( hbitmap )
  1696.           DeleteObject( hbitmap );
  1697.  
  1698.       DeleteDC( hmemDC );
  1699.       ReleaseDC( hwndPicture, hdc );
  1700.  
  1701.       return FALSE;
  1702.  
  1703.      }
  1704.  
  1705.  
  1706. // Function: StoreCurrentSystemPalette - stores the current system palette just
  1707. //                                       before calling RealizePalette.
  1708. //                                       This is also called during frame
  1709. //                                       wnd WM_PALETTECHANGED processing
  1710. // --------------------------------------------------------------------
  1711. // Parameters: HPALETTE      hpalPicture  Palette of picture that realized
  1712. //                           palette, otherwise NULL
  1713. //
  1714. // Returns:    VOID
  1715. // --------------------------------------------------------------------
  1716.    VOID FAR StoreCurrentSystemPalette( HPALETTE hpalPicture )
  1717.  
  1718.      {if( hpalPicture )
  1719.           g.hpalCurrentSystem = hpalPicture;
  1720.  
  1721.       return;
  1722.      }
  1723.  
  1724.  
  1725. // Function: KeyDownMessage - processes the WM_KEYDOWN message
  1726. // --------------------------------------------------------------------
  1727. // Parameters: HWND         hwndPicture    Handle of picture window
  1728. //             WPARAM       wParam         WM_KEYDOWN wParam
  1729. //             LPARAM       lParam         WM_KEYDOWN lParam
  1730. //
  1731. // Returns:    LONG         Generally 0L
  1732. // --------------------------------------------------------------------
  1733.    static LONG NEAR KeyDownMessage
  1734.                       ( HWND hwndPicture, WPARAM wParam, LPARAM lParam )
  1735.  
  1736.    // Process keyboard interface messages
  1737.  
  1738.      {NPPICTUREDATA   pPictureData;      // -> picture data struct
  1739.       WORD            wScroll;           // Scrolling parameter
  1740.  
  1741.       switch( wParam )
  1742.          {case VK_LEFT:
  1743.           case VK_RIGHT:
  1744.               if( ISKEYDOWN( VK_CONTROL ))
  1745.                   wScroll = ( wParam == VK_LEFT ) ? SB_PAGELEFT: SB_PAGERIGHT;
  1746.               else
  1747.                   wScroll = ( wParam == VK_LEFT ) ? SB_LINELEFT: SB_LINERIGHT;
  1748.  
  1749.               return ProcessHorzScroll( hwndPicture, wScroll, 0 );
  1750.  
  1751.           case VK_UP:
  1752.           case VK_DOWN:
  1753.               if( ISKEYDOWN( VK_CONTROL ))
  1754.                   wScroll = ( wParam == VK_UP ) ? SB_PAGEUP: SB_PAGEDOWN;
  1755.               else
  1756.                   wScroll = ( wParam == VK_UP ) ? SB_LINEUP: SB_LINEDOWN;
  1757.  
  1758.               return ProcessVertScroll( hwndPicture, wScroll, 0 );
  1759.  
  1760.           case VK_PRIOR:
  1761.           case VK_NEXT:
  1762.               if( ISKEYDOWN( VK_CONTROL ))
  1763.                   return ProcessHorzScroll( hwndPicture,
  1764.                       ( wParam == VK_PRIOR ? SB_PAGELEFT: SB_PAGERIGHT ), 0 );
  1765.               else
  1766.                   return ProcessVertScroll( hwndPicture,
  1767.                       ( wParam == VK_PRIOR ? SB_PAGEUP: SB_PAGEDOWN ), 0 );
  1768.  
  1769.           case VK_HOME:
  1770.           case VK_END:
  1771.               return ScrollToCorner( hwndPicture, wParam );
  1772.  
  1773.           case VK_ADD:
  1774.           case VK_SUBTRACT:
  1775.               if( (pPictureData = (NPPICTUREDATA)
  1776.                              GetWindowWord( hwndPicture, 0 )) &&
  1777.                                           pPictureData->zsZoomScroll.hwnd )
  1778.                   return SendMessage( pPictureData->zsZoomScroll.hwnd,
  1779.                                               WM_KEYDOWN, wParam, lParam );
  1780.               break;
  1781.  
  1782.          }
  1783.  
  1784.       return 0L;
  1785.  
  1786.      }
  1787.  
  1788.  
  1789. // Function: PrintPicture - prints indicated number of copies of
  1790. //                          the picture
  1791. // --------------------------------------------------------------------
  1792. // Parameters: HWND         hwndPicture     Handle of Picture window
  1793. //             LPPRINTDLG   lppd            -> to PRINTDLG struct created
  1794. //                                          by print common dialog
  1795. //
  1796. // Returns:    LONG         0L if successful
  1797. // --------------------------------------------------------------------
  1798.    static LONG NEAR PrintPicture( HWND hwndPicture, LPPRINTDLG lppd )
  1799.  
  1800.      {NPPICTUREDATA   pPictureData;   // -> picture data struct
  1801.       WORD            i;              // Counter
  1802.       DOCINFO         diDocInfo;      // Document info struct
  1803.       BOOL            bError;         // Error flag
  1804.       RECT            rcPicture;      // Picture rect
  1805.       int             nError;         // Error return
  1806.       int             xRes;           // Horz printer resolution
  1807.       int             yRes;           // Vert printer resolution
  1808.       int             xOffset;        // Horz offset to center picture
  1809.       int             yOffset;        // Vert offset to center picture
  1810.       OSErr           oserr;          // Error return from DrawPictureFile
  1811.       WORD            wWidthPage;     // Width of printed page in pixels
  1812.       WORD            wHeightPage;    // Height of printed page in pixels
  1813.  
  1814.  
  1815.       if( !(pPictureData =
  1816.                         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  1817.          {CommonTellUser( ViewerQueryResources(),
  1818.                                     VIEWER_STRING_NOPICDATA, NULL, MB_OK );
  1819.              // Turn off not reported flag
  1820.           return SP_ERROR &  ~SP_NOTREPORTED;
  1821.          }
  1822.  
  1823.       diDocInfo.cbSize      = sizeof( DOCINFO );
  1824.       diDocInfo.lpszDocName = pPictureData->szPictureName;
  1825.       diDocInfo.lpszOutput  = (LPSTR) NULL;
  1826.  
  1827.       bError = FALSE;
  1828.       oserr  = 0L;
  1829.       nError = SP_ERROR;
  1830.  
  1831.       wWidthPage  = GetDeviceCaps( lppd->hDC, HORZRES );
  1832.       wHeightPage = GetDeviceCaps( lppd->hDC, VERTRES );
  1833.  
  1834.          // get resolution of printer
  1835.       xRes = MulDiv( wWidthPage, 254,
  1836.                            GetDeviceCaps( lppd->hDC, HORZSIZE ) * 10 );
  1837.       yRes = MulDiv( wHeightPage, 254,
  1838.                            GetDeviceCaps( lppd->hDC, VERTSIZE ) * 10 );
  1839.  
  1840.          // Scale picture rect for differences in resolution
  1841.       rcPicture.right  = MulDiv( pPictureData->idImageInfo.width,
  1842.                           xRes, HIWORD( pPictureData->idImageInfo.hRes ));
  1843.       rcPicture.bottom = MulDiv( pPictureData->idImageInfo.height,
  1844.                           yRes, HIWORD( pPictureData->idImageInfo.vRes ));
  1845.       rcPicture.left = rcPicture.top = 0;
  1846.  
  1847.          // Now make sure that picture fits on page
  1848.       if( rcPicture.right > (int) wWidthPage )
  1849.          {rcPicture.bottom = MulDiv( rcPicture.bottom,
  1850.                                              wWidthPage, rcPicture.right );
  1851.           rcPicture.right = wWidthPage;
  1852.          }
  1853.       if( rcPicture.bottom > (int) wHeightPage )
  1854.          {rcPicture.right = MulDiv( rcPicture.right,
  1855.                                            wHeightPage, rcPicture.bottom );
  1856.           rcPicture.bottom = wHeightPage;
  1857.          }
  1858.  
  1859.          // Now center rect on page
  1860.       xOffset = ( wWidthPage  - rcPicture.right ) / 2;
  1861.       yOffset = ( wHeightPage - rcPicture.bottom ) / 2;
  1862.       OffsetRect( &rcPicture, xOffset, yOffset );
  1863.  
  1864.          // Start printing. Loop over number of copies
  1865.       if( StartDoc( lppd->hDC, &diDocInfo ) > 0 )
  1866.          {for( i=0; (i < lppd->nCopies) && !bError; i++)
  1867.             {if( StartPage( lppd->hDC ) > 0 )
  1868.                {if( (oserr = DrawPicture( lppd->hDC,
  1869.                           pPictureData->phPicture, &rcPicture, NULL )) != 0L )
  1870.                    {  // DrawPicture failed, abort the print
  1871.                     AbortDoc( lppd->hDC );
  1872.                     bError = TRUE;
  1873.                    }
  1874.                 else
  1875.                    {if( ( nError = EndPage( lppd->hDC )) < 0 )
  1876.                        bError = TRUE;
  1877.                    }
  1878.                }
  1879.              else
  1880.                 bError = TRUE;
  1881.             }
  1882.          }
  1883.       else
  1884.           bError = TRUE;
  1885.  
  1886.       if( !bError )
  1887.           EndDoc( lppd->hDC );
  1888.       else if( oserr )
  1889.          {CommonTellUser( ViewerQueryResources(),
  1890.                            VIEWER_STRING_DRAWPICFAIL,
  1891.                                       VIEWER_STRING_PRT_CAPTION, MB_OK );
  1892.              // Error has been reported, turn off "not reported" bit
  1893.           nError = SP_ERROR &  ~SP_NOTREPORTED;
  1894.          }
  1895.  
  1896.       return (LONG) nError;
  1897.      }
  1898.  
  1899.  
  1900. // Function: GetInfoDlgProc - Get Info dialog proc
  1901. // --------------------------------------------------------------------
  1902. // Parameters: As required by Microsoft Windows
  1903. //
  1904. // Returns:    As required by Microsoft Windows
  1905. // --------------------------------------------------------------------
  1906.    BOOL __export CALLBACK GetInfoDlgProc
  1907.                      ( HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1908.  
  1909.      {NPPICTUREDATA  pPictureData;   // -> picture data struct
  1910.       HWND           hwndPicture;    // Handle to picture window
  1911.       HWND           hwndCtl;        // Handle of control
  1912.       HDC            hdc;            // DC of control
  1913.       int            nHeight;        // Text height
  1914.  
  1915.  
  1916.       switch( msg )
  1917.          {case WM_INITDIALOG:
  1918.              hwndPicture = (HWND) SendMessage
  1919.                     ( ViewerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L );
  1920.  
  1921.                 // Use property to associate picture window handle with
  1922.                 // info dialog. This is necessary because MDI makes frame
  1923.                 // window the parent of all dialogs no matter what handle
  1924.                 // is used in the CreateDialog call
  1925.              SetProp( hdlg, GETINFOPICTUREPROP, (HANDLE) hwndPicture );
  1926.  
  1927.  
  1928.              if( pPictureData = (NPPICTUREDATA)
  1929.                                        GetWindowWord( hwndPicture, 0 ))
  1930.                 {pPictureData->hwndGetInfo = hdlg;
  1931.  
  1932.                  if( hdc = GetDC( hdlg ))
  1933.                     {nHeight = -MulDiv( 8, GetDeviceCaps( hdc, LOGPIXELSY ), 72 );
  1934.                      if( pPictureData->hfInfo = MakeAnArialFont( hdc, nHeight ))
  1935.                         {hwndCtl = GetWindow( hdlg, GW_CHILD );
  1936.                          while( hwndCtl )
  1937.                             {if( GetDlgCtrlID( hwndCtl ) != IDOK )
  1938.                                 SendMessage( hwndCtl, WM_SETFONT,
  1939.                                                  (WPARAM) pPictureData->hfInfo, 0 );
  1940.                              hwndCtl = GetWindow( hwndCtl, GW_HWNDNEXT );
  1941.                             }
  1942.                         }
  1943.                      ReleaseDC( hdlg, hdc );
  1944.                     }
  1945.  
  1946.                  FillPictureInfo( hdlg, pPictureData );
  1947.                 }
  1948.  
  1949.              return TRUE;
  1950.  
  1951.          case WM_ACTIVATE:
  1952.              ViewerSetActiveModeless( wParam, hdlg );
  1953.              return TRUE;
  1954.  
  1955.           case WM_COMMAND:
  1956.              return DestroyWindow( hdlg );
  1957.  
  1958. // WM_USER messages
  1959.  
  1960.           case WM_INFO_UPDATEFILENAME:
  1961.              hwndPicture = (HWND) GetProp( hdlg, GETINFOPICTUREPROP );
  1962.              if( pPictureData = (NPPICTUREDATA)
  1963.                                        GetWindowWord( hwndPicture, 0 ))
  1964.                  UpdateInfoFileName( hdlg, pPictureData );
  1965.  
  1966.              break;
  1967.  
  1968.           case WM_INFO_CURRENTSIZE:
  1969.              hwndPicture = (HWND) GetProp( hdlg, GETINFOPICTUREPROP );
  1970.              if( pPictureData = (NPPICTUREDATA)
  1971.                                        GetWindowWord( hwndPicture, 0 ))
  1972.                  UpdateInfoCurrentSize( hdlg, pPictureData );
  1973.  
  1974.              break;
  1975.  
  1976. // end WM_USER messages
  1977.  
  1978.           case WM_DESTROY:
  1979.              hwndPicture = (HWND) GetProp( hdlg, GETINFOPICTUREPROP );
  1980.              if( IsWindow( hwndPicture ) && ( pPictureData =
  1981.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  1982.                 {pPictureData->hwndGetInfo = NULL;
  1983.  
  1984.                  if( pPictureData->hfInfo )
  1985.                      DeleteObject( pPictureData->hfInfo );
  1986.                  pPictureData->hfInfo = NULL;
  1987.                 }
  1988.  
  1989.              RemoveProp( hdlg, GETINFOPICTUREPROP );
  1990.  
  1991.              return FALSE;
  1992.          }
  1993.  
  1994.       return FALSE;
  1995.  
  1996.      }
  1997.  
  1998.  
  1999. // Function: FillPictureInfo - Fills dialog controls with picture data
  2000. // --------------------- -----------------------------------------------
  2001. // Parameters: HWND           hdlg             Handle of dialog wnd
  2002. //             NPPICTUREDATA  pPictureData     -> to PICTUREDATA struct
  2003. //
  2004. // Returns:    VOID
  2005. // --------------------------------------------------------------------
  2006.    static VOID NEAR FillPictureInfo( HWND hdlg, NPPICTUREDATA pPictureData )
  2007.  
  2008.      {char      szBuffer[50];           // buffer
  2009.       char      szFormat[20];           // Format buffer
  2010.       WORD      wNormalWidth;           // Normal width of picture
  2011.       WORD      wNormalHeight;          // Normal height of picture
  2012.       DWORD     dwColors;               // Number of colors
  2013.       DWORD     dwSize;                 // Uncompressed size
  2014.       WORD      wIDString;              // Resource string id
  2015.  
  2016.  
  2017.     // Picture name: Append duplication index if > 0
  2018.       UpdateInfoFileName( hdlg, pPictureData );
  2019.  
  2020.     // Filesize
  2021.       SetDlgItemText( hdlg, IMAGE_INFO_FILESIZE,
  2022.                                   (LPSTR) pPictureData->szFileSizeOnDisk );
  2023.  
  2024.     // Current Width and Height
  2025.       UpdateInfoCurrentSize( hdlg, pPictureData );
  2026.  
  2027.     // Normal Width and Height
  2028.       wNormalWidth  = pPictureData->idImageInfo.width;
  2029.       wNormalHeight = pPictureData->idImageInfo.height;
  2030.       LoadString( ViewerQueryResources(), VIEWER_STRING_WANDH,
  2031.                                           szFormat, sizeof( szFormat ));
  2032.       wsprintf( szBuffer, szFormat, wNormalWidth, wNormalHeight );
  2033.       SetDlgItemText( hdlg, IMAGE_INFO_WANDH, szBuffer );
  2034.  
  2035.  
  2036.     // Resolution
  2037.       if( ((LONG) pPictureData->idImageInfo.hRes == -1L ) ||
  2038.                        ((LONG) pPictureData->idImageInfo.hRes == 0L ))
  2039.           LoadString( ViewerQueryResources(),
  2040.                  VIEWER_STRING_NORESOLUTION, szBuffer, sizeof( szBuffer ));
  2041.       else
  2042.          {LoadString( ViewerQueryResources(),
  2043.                  VIEWER_STRING_RESOLUTION, szFormat, sizeof( szFormat ));
  2044.           wsprintf( szBuffer, szFormat,
  2045.                                HIWORD( pPictureData->idImageInfo.hRes ));
  2046.          }
  2047.       SetDlgItemText( hdlg, IMAGE_INFO_RESOLUTION, szBuffer );
  2048.  
  2049.     // Normal colors
  2050.       switch( pPictureData->idImageInfo.depth )
  2051.          {case 1:        // Black and White
  2052.               wIDString = VIEWER_STRING_CLRS_BANDW;      break;
  2053.           case 1 + 32:   // 2 Grays
  2054.               wIDString = VIEWER_STRING_CLRS_2GRAYS;     break;
  2055.           case 2:        // 4 Colors
  2056.               wIDString = VIEWER_STRING_CLRS_4COLORS;    break;
  2057.           case 2 + 32:   // 4 Grays
  2058.               wIDString = VIEWER_STRING_CLRS_4GRAYS;     break;
  2059.           case 4:        // 16 Colors
  2060.               wIDString = VIEWER_STRING_CLRS_16COLORS;   break;
  2061.           case 4 + 32:   // 16 Grays
  2062.               wIDString = VIEWER_STRING_CLRS_16GRAYS;    break;
  2063.           case 8:        // 256 Colors
  2064.               wIDString = VIEWER_STRING_CLRS_256COLORS;  break;
  2065.           case 8 + 32:   // 256 Grays
  2066.               wIDString = VIEWER_STRING_CLRS_256GRAYS;   break;
  2067.           case 16:       // Thousands of Colors
  2068.               wIDString = VIEWER_STRING_CLRS_THOUSANDS;  break;
  2069.           case 24:       // Millions of Colors
  2070.               wIDString = VIEWER_STRING_CLRS_MILLIONS;   break;
  2071.           case 32:       // Millions of Colors+
  2072.               wIDString = VIEWER_STRING_CLRS_MILLNSPLUS; break;
  2073.           default:
  2074.               wIDString = 0xffff;
  2075.               if( pPictureData->idImageInfo.depth < 32 )
  2076.                  {LoadString( ViewerQueryResources(),
  2077.                      VIEWER_STRING_COLORS, szFormat, sizeof( szFormat ));
  2078.                   dwColors = 1L << pPictureData->idImageInfo.depth;
  2079.                   wsprintf( szBuffer, szFormat, dwColors );
  2080.                  }
  2081.               else
  2082.                  {szBuffer[0] = '\0';
  2083.                  }
  2084.               break;
  2085.          }
  2086.       if( wIDString != 0xffff )
  2087.           LoadString( ViewerQueryResources(),
  2088.                             wIDString, szBuffer, sizeof( szBuffer ));
  2089.       SetDlgItemText( hdlg, IMAGE_INFO_COLORS, szBuffer );
  2090.  
  2091.  
  2092.     // Compressor. Compressor type displayed is the string stored for use in
  2093.     //             the banner bar rather that the DWORD value such as 'jpeg'
  2094.       SetDlgItemText( hdlg, IMAGE_INFO_COMPRESSOR,
  2095.                                              pPictureData->szPictType );
  2096.  
  2097.  
  2098.     // Quality
  2099.       if( pPictureData->idImageInfo.CodecType )
  2100.          {*((PDWORD) &szBuffer) = pPictureData->idImageInfo.CodecType;
  2101.           szBuffer[ sizeof(DWORD) ] = '\0';
  2102.          }
  2103.       if( !pPictureData->idImageInfo.CodecType ||
  2104.                                      !lstrcmpi( szBuffer, "raw " ))
  2105.          {szBuffer[0] = '\0';
  2106.          }
  2107.       else
  2108.          {LoadString( ViewerQueryResources(),
  2109.                    VIEWER_STRING_QUALITY, szBuffer, sizeof( szBuffer ));
  2110.          }
  2111.       SetDlgItemText( hdlg, IMAGE_INFO_QUALITY, szBuffer );
  2112.  
  2113.  
  2114.     // Uncompressed size
  2115.       dwSize = ( (DWORD) wNormalWidth * wNormalHeight *
  2116.                              pPictureData->idImageInfo.depth ) / 8L;
  2117.       if( dwSize < 1000L )
  2118.          {wIDString = VIEWER_STRING_SIZEBYTES;
  2119.          }
  2120.       else
  2121.          {dwSize /= 1000L;
  2122.           wIDString = VIEWER_STRING_SIZEKBYTES;
  2123.          }
  2124.  
  2125.       LoadString( ViewerQueryResources(), wIDString,
  2126.                                      szFormat, sizeof( szFormat ));
  2127.       wsprintf( szBuffer, szFormat, dwSize );
  2128.       SetDlgItemText( hdlg, IMAGE_INFO_UNCOMPSIZE, szBuffer );
  2129.  
  2130.       return;
  2131.      }
  2132.  
  2133.  
  2134. // Function: UpdateInfoFileName - Updates the file name with the current
  2135. //                                instance count in the info dialog
  2136. // --------------------- -----------------------------------------------
  2137. // Parameters: HWND           hdlg             Handle of dialog wnd
  2138. //             NPPICTUREDATA  pPictureData     -> to PICTUREDATA struct
  2139. //
  2140. // Returns:    VOID
  2141. // --------------------------------------------------------------------
  2142.    static VOID NEAR UpdateInfoFileName
  2143.                            ( HWND hdlg, NPPICTUREDATA pPictureData )
  2144.  
  2145.      {char      szBuffer[MAX_NAME_LEN + 10];  // Name buffer
  2146.       char      szFormat[20];                 // Format buffer
  2147.  
  2148.       lstrcpy( szFormat, "%s%s" );
  2149.       if( pPictureData->wDuplicationIndex > 0 )
  2150.           lstrcat( szFormat, ":%u" );
  2151.       wsprintf( szBuffer, szFormat, (LPSTR) pPictureData->szPictureName,
  2152.                         (LPSTR) pPictureData->szPictureExt,
  2153.                                  pPictureData->wDuplicationIndex );
  2154.       AnsiUpper( szBuffer );
  2155.       SetDlgItemText( hdlg, IMAGE_INFO_NAME, (LPSTR) szBuffer );
  2156.  
  2157.       return;
  2158.      }
  2159.  
  2160. // Function: UpdateInfoCurrentSize - Updates the current size in the
  2161. //                                   info dialog
  2162. // --------------------- -----------------------------------------------
  2163. // Parameters: HWND           hdlg             Handle of dialog wnd
  2164. //             NPPICTUREDATA  pPictureData     -> to PICTUREDATA struct
  2165. //
  2166. // Returns:    VOID
  2167. // --------------------------------------------------------------------
  2168.    static VOID NEAR UpdateInfoCurrentSize
  2169.                            ( HWND hdlg, NPPICTUREDATA pPictureData )
  2170.  
  2171.      {char      szBuffer[50];           // buffer
  2172.       char      szFormat[20];           // Format buffer
  2173.  
  2174.       LoadString( ViewerQueryResources(), VIEWER_STRING_WANDH,
  2175.                                           szFormat, sizeof( szFormat ));
  2176.       wsprintf( szBuffer, szFormat,
  2177.                   pPictureData->rcCurPictureRect.right -
  2178.                                 pPictureData->rcCurPictureRect.left,
  2179.                   pPictureData->rcCurPictureRect.bottom -
  2180.                                 pPictureData->rcCurPictureRect.top );
  2181.       SetDlgItemText( hdlg, IMAGE_INFO_CURSIZE, szBuffer );
  2182.  
  2183.       return;
  2184.      }
  2185.  
  2186.  
  2187. // Function: InitializePopupMenus - Called just before the popup menus
  2188. //                                  are displayed
  2189. // --------------------------------------------------------------------
  2190. // Parameters: HWND         hwndPicture     Handle of Picture window
  2191. //             HMENU        hmenuPopup      Handle of popup menu
  2192. //             int          nPopupIndex     Index of popup
  2193. //
  2194. // Returns:    LONG         0L if successful
  2195. // --------------------------------------------------------------------
  2196.    static LONG NEAR InitializePopupMenus
  2197.                    ( HWND hwndPicture, HMENU hmenuPopup, int nPopupIndex )
  2198.  
  2199.      {NPPICTUREDATA    pPictureData;         // -> picture data struct
  2200.       char             szTitle[64];          // OLE Client doc title
  2201.       char             szItemFormat1[32];    // Item format string
  2202.       char             szItem1[128];         // New item string
  2203.       char             szItemFormat2[32];    // Item format string
  2204.       char             szItem2[128];         // New item string
  2205.  
  2206.       if( !(pPictureData =
  2207.                          (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  2208.          {CommonTellUser( ViewerQueryResources(),
  2209.                    VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  2210.           return 0L;
  2211.          }
  2212.  
  2213.          // Decrement index if maximized since MDI adds a system menu item
  2214.          // which puts count off by one
  2215.       if( IsZoomed( hwndPicture ))
  2216.           nPopupIndex--;
  2217.  
  2218.       if( nPopupIndex == MENU_FILE_POS )
  2219.         {   // See if wnd is an activated client object
  2220.           if( QTOLE_IsActiveObjectWnd
  2221.                               ( ViewerQueryOleData(), hwndPicture, szTitle ))
  2222.              {LoadString( ViewerQueryResources(),
  2223.                     VIEWER_STRING_OLECLOSE, szItemFormat1, sizeof( szItemFormat1 ));
  2224.               wsprintf( szItem1, szItemFormat1, (LPSTR) szTitle );
  2225.  
  2226.               LoadString( ViewerQueryResources(),
  2227.                     VIEWER_STRING_OLEEXIT, szItemFormat2, sizeof( szItemFormat2 ));
  2228.               wsprintf( szItem2, szItemFormat2, (LPSTR) szTitle );
  2229.              }
  2230.           else
  2231.              {LoadString( ViewerQueryResources(),
  2232.                          VIEWER_STRING_CLOSE, szItem1, sizeof( szItem1 ));
  2233.               LoadString( ViewerQueryResources(),
  2234.                          VIEWER_STRING_EXIT, szItem2, sizeof( szItem2 ));
  2235.              }
  2236.  
  2237.           DeleteMenu( hmenuPopup, VIEWER_FILE_CLOSE, MF_BYCOMMAND );
  2238.           InsertMenu( hmenuPopup, 1, MF_BYPOSITION,
  2239.                                              VIEWER_FILE_CLOSE, szItem1 );
  2240.           DeleteMenu( hmenuPopup, VIEWER_FILE_EXIT, MF_BYCOMMAND );
  2241.           InsertMenu( hmenuPopup, (UINT) -1, MF_BYPOSITION,
  2242.                                              VIEWER_FILE_EXIT, szItem2 );
  2243.          }
  2244.       else if( nPopupIndex == MENU_EDIT_POS )
  2245.          {EnableMenuItem( hmenuPopup, VIEWER_EDIT_COPYPICTURE,
  2246.                 ( IsIconic( hwndPicture ) ?  MF_GRAYED: MF_ENABLED ) |
  2247.                                                             MF_BYCOMMAND );
  2248.           EnableMenuItem( hmenuPopup, VIEWER_EDIT_OPTIONS,
  2249.                      ( IsIconic( hwndPicture ) ) ? MF_GRAYED: MF_ENABLED );
  2250.           EnableMenuItem( hmenuPopup, VIEWER_EDIT_CANCELSEL,
  2251.                  ( IsRectEmpty( &pPictureData->qtoleOptions.rcSelection ))?
  2252.                                                      MF_GRAYED: MF_ENABLED );
  2253.          }
  2254.       else if( nPopupIndex == MENU_IMAGE_POS )
  2255.          {CheckMenuItem( hmenuPopup, VIEWER_IMAGE_HALFSIZE,
  2256.                ( pPictureData->zsZoomScroll.wCurZoomIndex ==
  2257.                       VIEWER_IMAGE_HALFSIZE) ? MF_CHECKED: MF_UNCHECKED );
  2258.           CheckMenuItem( hmenuPopup, VIEWER_IMAGE_NORMALSIZE,
  2259.                ( pPictureData->zsZoomScroll.wCurZoomIndex ==
  2260.                       VIEWER_IMAGE_NORMALSIZE) ? MF_CHECKED: MF_UNCHECKED );
  2261.           CheckMenuItem( hmenuPopup, VIEWER_IMAGE_DOUBLESIZE,
  2262.                ( pPictureData->zsZoomScroll.wCurZoomIndex ==
  2263.                       VIEWER_IMAGE_DOUBLESIZE) ? MF_CHECKED: MF_UNCHECKED );
  2264.          }
  2265.  
  2266.       return 0L;
  2267.      }
  2268.  
  2269.  
  2270.  
  2271. // Function: SetOptionsDefaults - Set option defaults
  2272. // --------------------------------------------------------------------
  2273. // Parameters: HWND             hwndPicture      Picture hwnd
  2274. //             NPPICTUREDATA    pPictureData     -> picture data struct
  2275. //
  2276. // Returns:    VOID
  2277. // --------------------------------------------------------------------
  2278.    static VOID NEAR SetOptionsDefaults
  2279.                             ( HWND hwndPicture, NPPICTUREDATA pPictureData )
  2280.  
  2281.      {   // Preset copy struct parameters that do not change
  2282.       pPictureData->qtoleOptions.lStructSize   = sizeof( QTOLE_OPTIONSPICTURE );
  2283.       pPictureData->qtoleOptions.lVersion      = VERSION_1;
  2284.       pPictureData->qtoleOptions.wObjectType   = PICTURE_OBJECT;
  2285.       pPictureData->qtoleOptions.hwndObject    = hwndPicture;
  2286.  
  2287.       pPictureData->qtoleOptions.phPicture     = pPictureData->phPicture;
  2288.  
  2289.          // Query qtw.ini for defaults
  2290.       ViewerGetDefaultOptions( &pPictureData->qtoleOptions );
  2291.  
  2292.       lstrcpy( pPictureData->qtoleOptions.szCaption, pPictureData->szPictureName );
  2293.       lstrcat( pPictureData->qtoleOptions.szCaption, pPictureData->szPictureExt );
  2294.  
  2295.       return;
  2296.      }
  2297.  
  2298.  
  2299. // Function: UpdatePictForOptions - Sets the picture according to values set
  2300. //                                  in options struct
  2301. // --------------------------------------------------------------------
  2302. // Parameters: HWND          hwndPicture      Picture window handle
  2303. //             NPPICTUREDATA pPictureData     Picture data structure
  2304. //             BOOL          bCalledByOLE     TRUE if called by ole callback funct.
  2305. //
  2306. // Returns:    None
  2307. // --------------------------------------------------------------------
  2308.    VOID FAR UpdatePictForOptions
  2309.              ( HWND hwndPicture, NPPICTUREDATA pPictureData, BOOL bCalledByOLE )
  2310.  
  2311.      {LPQTOLE_OPTIONSPICTURE  lpOptions;
  2312.       POINT                   ptUL;
  2313.       WORD                    wZoomIndex;
  2314.  
  2315.       lpOptions = &pPictureData->qtoleOptions;
  2316.       if( lpOptions->bZoomHalf )
  2317.           SendMessage( hwndPicture, WM_COMMAND, VIEWER_IMAGE_HALFSIZE, 0L );
  2318.       else if( lpOptions->bZoomNormal )
  2319.           SendMessage( hwndPicture, WM_COMMAND, VIEWER_IMAGE_NORMALSIZE, 0L );
  2320.       else if( lpOptions->bZoomDouble )
  2321.           SendMessage( hwndPicture, WM_COMMAND, VIEWER_IMAGE_DOUBLESIZE, 0L );
  2322.       else if( bCalledByOLE )
  2323.          {wZoomIndex = ViewerQueryZoomIndex( lpOptions->wZoomCurrent );
  2324.           ZoomPicture( hwndPicture, wZoomIndex );
  2325.  
  2326.           if( !IsRectEmpty( &lpOptions->rcSelection ))
  2327.              {ptUL = *(LPPOINT) &lpOptions->rcSelection.left;
  2328.               ptUL.x = MulDiv( ptUL.x, (int) lpOptions->wZoomCurrent, 100 );
  2329.               ptUL.y = MulDiv( ptUL.y, (int) lpOptions->wZoomCurrent, 100 );
  2330.  
  2331.               ProcessHorzScroll( hwndPicture, SB_THUMBPOSITION, ptUL.x );
  2332.               ProcessVertScroll( hwndPicture, SB_THUMBPOSITION, ptUL.y );
  2333.  
  2334.               InvalidateRect( hwndPicture, NULL, TRUE );
  2335.              }
  2336.          }
  2337.  
  2338.       return;
  2339.      }
  2340.  
  2341.  
  2342. // Function: PopulateOptionsStruct - Populated the options structure
  2343. // --------------------------------------------------------------------
  2344. // Parameters: HWND          hwndPicture      Picture window handle
  2345. //             NPPICTUREDATA pPictureData     Picture data structure
  2346. //
  2347. // Returns:    None
  2348. // --------------------------------------------------------------------
  2349.    static VOID NEAR PopulateOptionsStruct
  2350.                          ( HWND hwndPicture, NPPICTUREDATA pPictureData )
  2351.  
  2352.      {  // Update these each time in case they get NULLed somewhere
  2353.       pPictureData->qtoleOptions.hwndObject = hwndPicture;
  2354.       pPictureData->qtoleOptions.phPicture  = pPictureData->phPicture;
  2355.  
  2356.       if( pPictureData->qtoleOptions.bZoomHalf )
  2357.           pPictureData->qtoleOptions.wZoomCurrent = 50;
  2358.       else if( pPictureData->qtoleOptions.bZoomNormal )
  2359.           pPictureData->qtoleOptions.wZoomCurrent = 100;
  2360.       else if( pPictureData->qtoleOptions.bZoomDouble )
  2361.           pPictureData->qtoleOptions.wZoomCurrent = 200;
  2362.       else
  2363.           pPictureData->qtoleOptions.wZoomCurrent =
  2364.                    ViewerQueryZoomMultiplier
  2365.                                   ( pPictureData->zsZoomScroll.wCurZoomIndex );
  2366.       return;
  2367.      }
  2368.  
  2369.  
  2370. //  The remaining functions are the query functions called by other modules
  2371.  
  2372. // Function: ViewerQueryActivePictureName - Query name of active picture
  2373. // --------------------------------------------------------------------
  2374. // Parameters: LPSTR      lpBuffer       string buffer
  2375. //
  2376. // Returns:    LPSTR      lpBuffer       Name of active picture
  2377. // --------------------------------------------------------------------
  2378.    LPSTR FAR ViewerQueryActivePictureName( LPSTR lpBuffer )
  2379.  
  2380.      {HWND            hwndPicture;    // Handle to active window
  2381.       NPPICTUREDATA   pPictureData;   // -> picture data struct
  2382.  
  2383.       hwndPicture = (HWND) SendMessage
  2384.                     ( ViewerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L );
  2385.       *lpBuffer = 0;
  2386.       if( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))
  2387.           lstrcpy( lpBuffer, pPictureData->szPictureName );
  2388.  
  2389.       return lpBuffer;
  2390.      }
  2391.  
  2392.